Project

General

Profile

Revision 128

Added by Jason knichel over 16 years ago

moved the command parsing into its own class

View differences:

trunk/code/projects/colonet/ColonetServer/Command.cpp
1
/**
2
 * @file Command.cpp
3
 *
4
 * @author Jason Knichel
5
 * @date 10/9/07
6
 */
7

  
8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <string.h>
11
#include <ctype.h>
12

  
13
#include "includes/Command.h"
14
#include "includes/ConnectionPool.h"
15

  
16
Command::Command() {
17
}
18

  
19
Command::~Command() {
20
}
21

  
22
//TODO: write a function to write data into the write buffers (jason: what was this referring to?)
23
int Command::parse_command(char* command, int pool_index, ConnectionPool * connection_pool) {
24
  char tokens[MAX_TOKENS][MAX_TOKEN_SIZE];
25
  unsigned char int_tokens[MAX_TOKENS];
26
  int number_tokens = 0;
27
  char* end_pointer = NULL;
28
  int command_id;
29
  int i;
30
  unsigned char arguments[PACKET_DATA_LEN];
31

  
32
  memset(arguments, 1, PACKET_DATA_LEN);
33

  
34
  if (!command) {
35
    return -1;
36
  }
37

  
38
  if (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
    int number_int_tokens = number_tokens;
56

  
57
    // Convert tokens to ints 
58
    for (i = ROBOT_COMMAND_OFFSET; i < number_int_tokens; i++) {
59
      int_tokens[i-ROBOT_COMMAND_OFFSET] = atoi(tokens[i]);
60
    }
61

  
62
    // Fill arguments buffer with arguments 
63
    for (i = ROBOT_COMMAND_LEN; i < number_int_tokens-ROBOT_COMMAND_OFFSET;
64
         i++) {
65
      arguments[i-ROBOT_COMMAND_LEN] = int_tokens[i];
66
    }
67

  
68
    // Check the tokens 
69
    if (check_tokens(int_tokens, number_int_tokens) < 0) {
70
      fprintf(stderr, "%s: Error - Invalid command/request.\n", __FUNCTION__);
71
      return 0;
72
    }
73

  
74
    /*  
75
    // Send packet to robot 
76
    fprintf(stderr, "Calling colonet_wl_send(%d, %d, %d, arguments)\n", 
77
            int_tokens[0], int_tokens[1], int_tokens[2]);
78
    colonet_wl_send(pool_index, int_tokens[0],
79
                    (ColonetMessageType)int_tokens[1], int_tokens[2],
80
                    arguments);
81
    */
82
  } else if (command_id == REQUEST_FROM_SERVER) {
83
    if (number_tokens < 2)
84
      return -1;
85

  
86
    end_pointer=NULL;
87
    int second_token = strtol(tokens[1], &end_pointer, 10);
88

  
89
    if (!end_pointer || *end_pointer != '\0') {
90
      printf("There was an error converting second token into a number.\n");
91
      return -1;
92
    }
93
    
94
    //TODO: move REQUEST_BOM_MATRIX stuff into a private function
95
    if (second_token == REQUEST_BOM_MATRIX) {
96
      //TODO: rename to indicate its actually the response message
97
      char bom_matrix_buffer[MAX_RESPONSE_LEN];
98
      char temp_bom_matrix_buffer[MAX_RESPONSE_LEN];
99
 
100
      //TODO: change after we start keeping track of bom matrix
101
      int number_robots = rand()%10;
102
      int bom_matrix[number_robots][number_robots];
103
      for (int ii = 0; ii < number_robots; ii++) {
104
        for (int j = 0; j < number_robots; j++) {
105
          //do this to generate some -1 values which mean they can't see each other
106
          int matrix_value = rand()%(number_robots+1)-1;
107
          bom_matrix[ii][j] = matrix_value;
108
        }
109
      }
110

  
111
      printf("number of robots is %d\n", number_robots);
112

  
113
      //TODO: separate parameters with spaces
114
      //TODO: make this better
115
      //TODO: make sure I don't need to do MAX_RESPONSE_LENGTH-1
116
      snprintf(bom_matrix_buffer,MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_BOM_MATRIX, number_robots);
117
      for (int ii = 0; ii < number_robots; ii++) {
118
        for (int j = 0; j < number_robots; j++) {
119
          //TODO: don't use strcpy
120
          strcpy(temp_bom_matrix_buffer, bom_matrix_buffer);
121
          //TODO: put length checking in here so array doesn't go out of bounds
122
          //TODO: maybe use strncat?
123
          strcat(temp_bom_matrix_buffer," %d");
124
          snprintf(bom_matrix_buffer, MAX_RESPONSE_LEN, temp_bom_matrix_buffer, bom_matrix[ii][j]);
125
        }
126
      }
127
      strcat(bom_matrix_buffer,"\n");
128
      connection_pool->write_to_client(pool_index, bom_matrix_buffer, strlen(bom_matrix_buffer));
129
      printf("Sending %s", bom_matrix_buffer);
130
    } else if (second_token == REQUEST_XBEE_IDS) {
131
      //TODO: move this into private function
132
      //TODO: make this better
133
      int number_robots = rand() % 10;
134

  
135
      char xbee_id_buffer[MAX_RESPONSE_LEN];
136
      char temp_xbee_id_buffer[MAX_RESPONSE_LEN];
137
      
138
      snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_XBEE_IDS, number_robots);
139
      
140
      printf("number of robots is %d\n", number_robots);
141

  
142
      for (int ii = 0; ii < number_robots; ii++) {
143
        strcpy(temp_xbee_id_buffer, xbee_id_buffer);
144
        //TODO: put length checking in here so array doesn't go out of bounds
145
        //TODO: maybe use strncat?
146
        strcat(temp_xbee_id_buffer, " %d");
147
        snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, temp_xbee_id_buffer, ii);
148
      }
149
      strcat(xbee_id_buffer, "\n");
150
      connection_pool->write_to_client(pool_index, xbee_id_buffer, strlen(xbee_id_buffer));
151
      printf("Sending %s", xbee_id_buffer);
152
    } else {
153
      char * my_current_message = "Hi, how are you?\n";
154
      printf("Sending %s\n", my_current_message);
155
      connection_pool->write_to_client(pool_index, my_current_message, strlen(my_current_message));
156
    }
157
  }
158

  
159
  return 0;
160
}
161

  
162
/**
163
 * @brief Breaks a command up into tokens
164
 *
165
 * @param command The command to tokenize
166
 * @param tokens A two dimensional character array to store the tokens in
167
 *
168
 * @return 0 on success, negative error code on failure
169
 */
170
int Command::tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]) {
171
  char* next_token = command;
172
  char* end_token = NULL;
173
  int number_tokens = 0;
174

  
175
  if (!command) {
176
    return -1;
177
  }
178

  
179
  while ((end_token = strstr(next_token, " "))) {
180
    *end_token = '\0';
181

  
182
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
183
      return -1;
184
    }
185

  
186
    strcpy(tokens[number_tokens], next_token);
187

  
188
    number_tokens++;
189
    next_token = end_token + 1;
190

  
191
    while (isspace(*next_token) && *next_token != '\0') {
192
      next_token++;
193
    }
194
  }
195

  
196
  if (end_token == NULL && *next_token != '\0') {
197
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
198
      return -1;
199
    }
200

  
201
    strcpy(tokens[number_tokens], next_token);
202

  
203
    number_tokens++;
204
  }
205

  
206
  return number_tokens;
207
}
208

  
209

  
210
/** 
211
 * @brief checks a list of tokens to see if it's valid
212
 *
213
 * @param tokens The tokens to check
214
 * @param number_tokens The number of tokens contained in the tokens parameter
215
 *
216
 * @return 0 if tokens is valid
217
 */
218
int Command::check_tokens(unsigned char* tokens, int number_tokens) {
219
  if (number_tokens > 3 + PACKET_DATA_LEN) {
220
    /* Too many tokens */
221
    return -1;
222
  }
223

  
224
  if (number_tokens < 3) {
225
    /* Not enough tokens */
226
    return -1;
227
  }
228
  
229
  if (tokens[1] != COLONET_REQUEST && tokens[1] != COLONET_COMMAND) {
230
    /* Invalid message type */
231
    return -1;
232
  }
233

  
234
  return 0;
235
}
trunk/code/projects/colonet/ColonetServer/includes/Command.h
1
/**
2
 * @file Command.h
3
 *
4
 * @author Jason Knichel
5
 * @date 10/9/07
6
 */
7

  
8
#ifndef COMMAND_H
9
#define COMMAND_H
10

  
11
#include "ConnectionPool.h"
12

  
13
class Command {
14
 public:
15
  Command();
16
  ~Command();
17

  
18
  int parse_command(char* command, int pool_index, ConnectionPool * connection_pool);
19
  int tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]);
20
  int check_tokens(unsigned char* tokens, int number_tokens);
21

  
22

  
23
};
24

  
25

  
26
#endif
trunk/code/projects/colonet/ColonetServer/ConnectionPool.cpp
15 15

  
16 16
#include "includes/ConnectionPool.h"
17 17
#include "includes/client.h"
18
#include "includes/Command.h"
18 19
#include "../lib/colonet_defs.h"
19 20
#include <colonet_wireless.h>
20 21

  
......
227 228
            break;
228 229
          }
229 230

  
230
          if (parse_command(temporary_command_buffer, i) < 0) {
231
	  Command command;
232
          if (command.parse_command(temporary_command_buffer, i, this) < 0) {
231 233
            printf("There was an error parsing command\n");
232 234
            break;
233 235
          }
......
374 376
  write_set = new_set;
375 377
}
376 378

  
377
//TODO: move the command stuff into their own class and have whatever wants to parse a command
378
//  first instantiate a command object and then call parse command
379
//   In order to do that, have to break dependencies between parse_command and connection_pool
380
//TODO: write a function to write data into the write buffers (jason: what was this referring to?)
381
int ConnectionPool::parse_command(char* command, int pool_index) {
382
  char tokens[MAX_TOKENS][MAX_TOKEN_SIZE];
383
  unsigned char int_tokens[MAX_TOKENS];
384
  int number_tokens = 0;
385
  char* end_pointer = NULL;
386
  int command_id;
387
  int i;
388
  unsigned char arguments[PACKET_DATA_LEN];
389 379

  
390
  memset(arguments, 1, PACKET_DATA_LEN);
391

  
392
  if (!command) {
393
    return -1;
394
  }
395

  
396
  if (pool_index < 0) {
397
    return -1;
398
  }
399

  
400
  if (pool_index >= next_available_slot) {
401
    return -1;
402
  }
403

  
404
  if ((number_tokens = tokenize_command(command, tokens)) < 0) {
405
    return -1;
406
  }
407

  
408
  //the 10 in the function call indicates number is base 10
409
  command_id = strtol(tokens[0], &end_pointer, 10);
410

  
411
  if (!end_pointer || *end_pointer != '\0') {
412
    printf("There was an error converting first token into a number.\n");
413
    return -1;
414
  }
415

  
416
  if (command_id == SEND_TO_ROBOT) {
417
    int number_int_tokens = number_tokens;
418

  
419
    // Convert tokens to ints 
420
    for (i = ROBOT_COMMAND_OFFSET; i < number_int_tokens; i++) {
421
      int_tokens[i-ROBOT_COMMAND_OFFSET] = atoi(tokens[i]);
422
    }
423
    /* we removed the request from robot constant
424
    if (command_id == REQUEST_FROM_ROBOT) {
425
      if (i < MAX_TOKENS) {
426
        for (;i >= 4; i--) {
427
          int_tokens[i] = int_tokens[i-1];
428
        }
429
        int_tokens[3] = pool_index;
430
        number_int_tokens++;
431
      } else {
432
        //TODO: send an error back to client here also
433
        fprintf(stderr, "Client attempted to request data from the robot but there was not enough room to put in the client's id.\n");
434
        return -1;
435
      }
436
    }
437
    */
438

  
439
    // Fill arguments buffer with arguments 
440
    for (i = ROBOT_COMMAND_LEN; i < number_int_tokens-ROBOT_COMMAND_OFFSET;
441
         i++) {
442
      arguments[i-ROBOT_COMMAND_LEN] = int_tokens[i];
443
    }
444

  
445
    // Check the tokens 
446
    if (check_tokens(int_tokens, number_int_tokens) < 0) {
447
      fprintf(stderr, "%s: Error - Invalid command/request.\n", __FUNCTION__);
448
      return 0;
449
    }
450

  
451
    /*  
452
    // Send packet to robot 
453
    fprintf(stderr, "Calling colonet_wl_send(%d, %d, %d, arguments)\n", 
454
            int_tokens[0], int_tokens[1], int_tokens[2]);
455
    colonet_wl_send(pool_index, int_tokens[0],
456
                    (ColonetMessageType)int_tokens[1], int_tokens[2],
457
                    arguments);
458
    */
459
  } else if (command_id == REQUEST_FROM_SERVER) {
460
    if (number_tokens < 2)
461
      return -1;
462

  
463
    end_pointer=NULL;
464
    int second_token = strtol(tokens[1], &end_pointer, 10);
465

  
466
    if (!end_pointer || *end_pointer != '\0') {
467
      printf("There was an error converting second token into a number.\n");
468
      return -1;
469
    }
470
    
471
    //TODO: move REQUEST_BOM_MATRIX stuff into a private function
472
    if (second_token == REQUEST_BOM_MATRIX) {
473
      //TODO: rename to indicate its actually the response message
474
      char bom_matrix_buffer[MAX_RESPONSE_LEN];
475
      char temp_bom_matrix_buffer[MAX_RESPONSE_LEN];
476
 
477
      //TODO: change after we start keeping track of bom matrix
478
      int number_robots = rand()%10;
479
      int bom_matrix[number_robots][number_robots];
480
      for (int ii = 0; ii < number_robots; ii++) {
481
        for (int j = 0; j < number_robots; j++) {
482
          //do this to generate some -1 values which mean they can't see each other
483
          int matrix_value = rand()%(number_robots+1)-1;
484
          bom_matrix[ii][j] = matrix_value;
485
        }
486
      }
487

  
488
      printf("number of robots is %d\n", number_robots);
489

  
490
      //TODO: separate parameters with spaces
491
      //TODO: make this better
492
      //TODO: make sure I don't need to do MAX_RESPONSE_LENGTH-1
493
      snprintf(bom_matrix_buffer,MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_BOM_MATRIX, number_robots);
494
      for (int ii = 0; ii < number_robots; ii++) {
495
        for (int j = 0; j < number_robots; j++) {
496
          //TODO: don't use strcpy
497
          strcpy(temp_bom_matrix_buffer, bom_matrix_buffer);
498
          //TODO: put length checking in here so array doesn't go out of bounds
499
          //TODO: maybe use strncat?
500
          strcat(temp_bom_matrix_buffer," %d");
501
          snprintf(bom_matrix_buffer, MAX_RESPONSE_LEN, temp_bom_matrix_buffer, bom_matrix[ii][j]);
502
        }
503
      }
504
      strcat(bom_matrix_buffer,"\n");
505
      write_to_client(pool_index, bom_matrix_buffer, strlen(bom_matrix_buffer));
506
      printf("Sending %s", bom_matrix_buffer);
507
    } else if (second_token == REQUEST_XBEE_IDS) {
508
      //TODO: move this into private function
509
      //TODO: make this better
510
      int number_robots = rand() % 10;
511

  
512
      char xbee_id_buffer[MAX_RESPONSE_LEN];
513
      char temp_xbee_id_buffer[MAX_RESPONSE_LEN];
514
      
515
      snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_XBEE_IDS, number_robots);
516
      
517
      printf("number of robots is %d\n", number_robots);
518

  
519
      for (int ii = 0; ii < number_robots; ii++) {
520
        strcpy(temp_xbee_id_buffer, xbee_id_buffer);
521
        //TODO: put length checking in here so array doesn't go out of bounds
522
        //TODO: maybe use strncat?
523
        strcat(temp_xbee_id_buffer, " %d");
524
        snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, temp_xbee_id_buffer, ii);
525
      }
526
      strcat(xbee_id_buffer, "\n");
527
      write_to_client(pool_index, xbee_id_buffer, strlen(xbee_id_buffer));
528
      printf("Sending %s", xbee_id_buffer);
529
    } else {
530
      char * my_current_message = "Hi, how are you?\n";
531
      printf("Sending %s\n", my_current_message);
532
      write_to_client(pool_index, my_current_message, strlen(my_current_message));
533
    }
534
  }
535

  
536
  return 0;
537
}
538

  
539
/**
540
 * @brief Breaks a command up into tokens
541
 *
542
 * @param command The command to tokenize
543
 * @param tokens A two dimensional character array to store the tokens in
544
 *
545
 * @return 0 on success, negative error code on failure
546
 */
547
int ConnectionPool::tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]) {
548
  char* next_token = command;
549
  char* end_token = NULL;
550
  int number_tokens = 0;
551

  
552
  if (!command) {
553
    return -1;
554
  }
555

  
556
  while ((end_token = strstr(next_token, " "))) {
557
    *end_token = '\0';
558

  
559
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
560
      return -1;
561
    }
562

  
563
    strcpy(tokens[number_tokens], next_token);
564

  
565
    number_tokens++;
566
    next_token = end_token + 1;
567

  
568
    while (isspace(*next_token) && *next_token != '\0') {
569
      next_token++;
570
    }
571
  }
572

  
573
  if (end_token == NULL && *next_token != '\0') {
574
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
575
      return -1;
576
    }
577

  
578
    strcpy(tokens[number_tokens], next_token);
579

  
580
    number_tokens++;
581
  }
582

  
583
  return number_tokens;
584
}
585

  
586
/** 
587
 * @brief checks a list of tokens to see if it's valid
588
 *
589
 * @param tokens The tokens to check
590
 * @param number_tokens The number of tokens contained in the tokens parameter
591
 *
592
 * @return 0 if tokens is valid
593
 */
594
int ConnectionPool::check_tokens(unsigned char* tokens, int number_tokens) {
595
  if (number_tokens > 3 + PACKET_DATA_LEN) {
596
    /* Too many tokens */
597
    return -1;
598
  }
599

  
600
  if (number_tokens < 3) {
601
    /* Not enough tokens */
602
    return -1;
603
  }
604
  
605
  if (tokens[1] != COLONET_REQUEST && tokens[1] != COLONET_COMMAND) {
606
    /* Invalid message type */
607
    return -1;
608
  }
609

  
610
  return 0;
611
}
trunk/code/projects/colonet/ColonetServer/Makefile
3 3
CC = g++
4 4
CFLAGS = -Wall -Wshadow -Wextra -g
5 5

  
6
COLONETCPPFILES = ColonetServer.cpp client.cpp ConnectionPool.cpp
6
COLONETCPPFILES = ColonetServer.cpp client.cpp ConnectionPool.cpp Command.cpp
7 7
COLONETCPPOBJECTS = $(COLONETCPPFILES:.cpp=.o)
8 8
COLONETFILES = options.c
9 9
COLONETOBJECTS = $(COLONETFILES:.c=.o)

Also available in: Unified diff