Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / ColonetServer / Command.cpp @ 445

History | View | Annotate | Download (7.95 KB)

1
/**
2
 * @file Command.cpp
3
 *
4
 * @author Jason Knichel
5
 * @date 10/9/07
6
 *
7
 * @todo make it so command doesn't rely on connection pool.  have methods
8
 *       that may return a response return it by getting a response array passed in to them
9
 *       that they fill in and then colonet server takes the contents of that response array
10
 *       and sends it to the appropriate client
11
 */
12

    
13
#include <ctype.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17

    
18
#include <colonet_wireless.h>
19

    
20
#include <Command.h>
21
#include <ConnectionPool.h>
22

    
23
Command::Command(ConnectionPool * connection_pool_temp) {
24
  connection_pool = connection_pool_temp;
25
}
26

    
27
Command::~Command() {}
28

    
29
/**
30
* Called by connection pool to parse command from client.
31
*/
32
int Command::parse_command(char* command, int pool_index) {
33
  char tokens[MAX_TOKENS][MAX_TOKEN_SIZE];
34
  int number_tokens = 0;
35
  char* end_pointer = NULL;
36
  int command_id;
37

    
38
  if (!connection_pool || !command || pool_index < 0) {
39
    return -1;
40
  }
41

    
42
  if ((number_tokens = tokenize_command(command, tokens)) < 0) {
43
    return -1;
44
  }
45

    
46
  //the 10 in the function call indicates number is base 10
47
  command_id = strtol(tokens[0], &end_pointer, 10);
48

    
49
  if (!end_pointer || *end_pointer != '\0') {
50
    printf("There was an error converting first token into a number.\n");
51
    return -1;
52
  }
53

    
54
  if (command_id == SEND_TO_ROBOT) {
55
    if (parse_send_to_robot(number_tokens, tokens, pool_index)) {
56
      fprintf(stderr, "parse_send_to_robot failed.\n");
57
      return -1;
58
    }
59
  } else if (command_id == REQUEST_FROM_SERVER) {
60
    if (parse_request_from_server(number_tokens, tokens, pool_index)) {
61
      return -1;
62
    }
63
  }
64

    
65
  return 0;
66
}
67

    
68
/**
69
 * @brief Breaks a command up into tokens
70
 *
71
 * @param command The command to tokenize
72
 * @param tokens A two dimensional character array to store the tokens in
73
 *
74
 * @return 0 on success, negative error code on failure
75
 */
76
int Command::tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]) {
77
  char* next_token = command;
78
  char* end_token = NULL;
79
  int number_tokens = 0;
80

    
81
  if (!command) {
82
    return -1;
83
  }
84

    
85
  while ((end_token = strstr(next_token, " "))) {
86
    *end_token = '\0';
87

    
88
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
89
      return -1;
90
    }
91

    
92
    strcpy(tokens[number_tokens], next_token);
93

    
94
    number_tokens++;
95
    next_token = end_token + 1;
96

    
97
    while (isspace(*next_token) && *next_token != '\0') {
98
      next_token++;
99
    }
100
  }
101

    
102
  if (end_token == NULL && *next_token != '\0') {
103
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
104
      return -1;
105
    }
106

    
107
    strcpy(tokens[number_tokens], next_token);
108

    
109
    number_tokens++;
110
  }
111

    
112
  return number_tokens;
113
}
114

    
115
/**
116
 * @brief checks a list of tokens to see if it's valid
117
 *
118
 * @param tokens The tokens to check
119
 * @param number_tokens The number of tokens contained in the tokens parameter
120
 *
121
 * @return 0 if tokens is valid
122
 */
123
int Command::check_tokens(unsigned char* tokens, int number_tokens) {
124
  if (number_tokens > 3 + PACKET_DATA_LEN) {
125
    /* Too many tokens */
126
    return -1;
127
  }
128

    
129
  if (number_tokens < 3) {
130
    /* Not enough tokens */
131
    return -1;
132
  }
133

    
134
  if (tokens[1] != COLONET_REQUEST && tokens[1] != COLONET_COMMAND) {
135
    /* Invalid message type */
136
    return -1;
137
  }
138

    
139
  return 0;
140
}
141

    
142
/**
143
* @brief Sends parsed command from server to robot(s).
144
*/
145
int Command::parse_send_to_robot(int number_int_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index) {
146
  unsigned char int_tokens[MAX_TOKENS], arguments[PACKET_DATA_LEN];
147

    
148
  memset(arguments, 1, PACKET_DATA_LEN);
149

    
150
  // Convert tokens to ints
151
  for (int i = ROBOT_COMMAND_OFFSET; i < number_int_tokens; i++) {
152
    int_tokens[i-ROBOT_COMMAND_OFFSET] = atoi(tokens[i]);
153
  }
154

    
155
  // Fill arguments buffer with arguments
156
  for (int i = ROBOT_COMMAND_LEN; i < number_int_tokens-ROBOT_COMMAND_OFFSET; i++) {
157
    arguments[i-ROBOT_COMMAND_LEN] = int_tokens[i];
158
  }
159

    
160
  // Check the tokens
161
  if (check_tokens(int_tokens, number_int_tokens) < 0) {
162
    fprintf(stderr, "%s: Error - Invalid robot command/request.\n", __FUNCTION__);
163
    return -1;
164
  }
165

    
166
  printf("parsed command from internet client: ");
167
  for (int i = 0; i < number_int_tokens - ROBOT_COMMAND_OFFSET; i++) {
168
    printf("%d ", int_tokens[i]);
169
  }
170
  printf("\n");
171

    
172
  // Send packet to robot
173
  if (colonet_wl_send((short)pool_index, int_tokens[0], (ColonetRobotMessageType)int_tokens[1], int_tokens[2],
174
    arguments) != 0) {
175
    fprintf(stderr, "Error - Colonet_wl_send failed.\n");
176
    exit(1);
177
  }
178

    
179
  return 0;
180
}
181

    
182
/**
183
* 
184
*/
185
int Command::parse_request_from_server(int number_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index) {
186
  char* end_pointer = NULL;
187

    
188
  if (!connection_pool) {
189
    return -1;
190
  }
191

    
192
  if (number_tokens < 2) {
193
    return -1;
194
  }
195

    
196
  end_pointer=NULL;
197
  int second_token = strtol(tokens[1], &end_pointer, 10);
198

    
199
  if (!end_pointer || *end_pointer != '\0') {
200
    printf("There was an error converting second token into a number.\n");
201
    return -1;
202
  }
203

    
204
  switch (second_token) {
205
  case REQUEST_BOM_MATRIX:
206
    if (parse_request_bom_matrix(pool_index)) {
207
      return -1;
208
    }
209
    break;
210

    
211
  case REQUEST_XBEE_IDS:
212
    if (parse_request_xbee_ids(pool_index)) {
213
      return -1;
214
    }
215
    break;
216

    
217
  case CLIENT_REQUEST_ROBOT_POSITIONS:
218
    if (parse_request_robot_positions(pool_index)) {
219
      return -1;
220
    }
221
    break;
222

    
223
  default:
224
    char * my_current_message = "Hi, how are you?\n";
225
    printf("Sending %s\n", my_current_message);
226
    connection_pool->write_to_client(pool_index, my_current_message, strlen(my_current_message));
227
    break;
228
  }
229

    
230
  return 0;
231
}
232

    
233
int Command::parse_request_bom_matrix(int pool_index) {
234
  char response_bom_matrix_buffer[MAX_RESPONSE_LEN];
235
  char temp_bom_matrix_buffer[MAX_RESPONSE_LEN];
236

    
237
  if (!connection_pool) {
238
    return -1;
239
  }
240

    
241
  int num_robots;
242
  int * xbee_ids;
243
  int** bom_matrix = colonet_get_sensor_matrix(&num_robots, &xbee_ids);
244

    
245
  printf("number of robots is %d\n", num_robots);
246

    
247
  //TODO: make this better
248
  //TODO: make sure I don't need to do MAX_RESPONSE_LENGTH-1
249
  snprintf(response_bom_matrix_buffer, MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_BOM_MATRIX,
250
           num_robots);
251
  for (int i = 0; i < num_robots; i++) {
252
    for (int j = 0; j < num_robots; j++) {
253
      //TODO: don't use strcpy
254
      strcpy(temp_bom_matrix_buffer, response_bom_matrix_buffer);
255
      //TODO: put length checking in here so array doesn't go out of bounds
256
      //TODO: maybe use strncat?
257
      strcat(temp_bom_matrix_buffer," %d");
258
      snprintf(response_bom_matrix_buffer, MAX_RESPONSE_LEN, temp_bom_matrix_buffer, bom_matrix[i][j]);
259
    }
260
  }
261
  strcat(response_bom_matrix_buffer,"\n");
262
  connection_pool->write_to_client(pool_index, response_bom_matrix_buffer, strlen(response_bom_matrix_buffer));
263
  printf("Sending %s", response_bom_matrix_buffer);
264
  
265
  for (int i = 0; i < num_robots; i++) {
266
    free(bom_matrix[i]);
267
  }
268
  free(bom_matrix);
269

    
270
  free(xbee_ids);
271

    
272
  return 0;
273
}
274

    
275
int Command::parse_request_robot_positions(int pool_index) {
276
  printf("TODO - parse_request_robot_positions\n");
277
  return 0;
278
}
279

    
280
int Command::parse_request_xbee_ids(int pool_index) {
281
  char temp_xbee_id_buffer[MAX_RESPONSE_LEN];
282
  char xbee_id_buffer[MAX_RESPONSE_LEN];
283

    
284
  int num_robots;
285
  int* xbee_ids = colonet_get_xbee_ids(&num_robots);
286

    
287
  printf("num_robots: %d\n", num_robots);
288
  printf("xbee_ids: ");
289
  for (int i = 0; i < num_robots; i++) {
290
    printf("%d ", xbee_ids[i]);
291
  }
292
  printf("\n");
293

    
294
  if (!connection_pool) {
295
    return -1;
296
  }
297

    
298
  snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_XBEE_IDS, num_robots);
299

    
300
  for (int i = 0; i < num_robots; i++) {
301
    strcpy(temp_xbee_id_buffer, xbee_id_buffer);
302
    //TODO: put length checking in here so array doesn't go out of bounds
303
    //TODO: maybe use strncat?
304
    strcat(temp_xbee_id_buffer, " %d");
305
    snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, temp_xbee_id_buffer, xbee_ids[i]);
306
  }
307
  strcat(xbee_id_buffer, "\n");
308
  connection_pool->write_to_client(pool_index, xbee_id_buffer, strlen(xbee_id_buffer));
309
  printf("Sending %s", xbee_id_buffer);
310

    
311
  free(xbee_ids);
312

    
313
  return 0;
314
}