root / trunk / code / projects / colonet / ColonetServer / ConnectionPool.cpp @ 123
History | View | Annotate | Download (17.7 KB)
1 | 11 | emarinel | /**
|
---|---|---|---|
2 | 29 | jknichel | * @file ConnectionPool.cpp
|
3 | *
|
||
4 | 11 | emarinel | * @author Jason Knichel
|
5 | * @date 7/22/07
|
||
6 | */
|
||
7 | |||
8 | #include <sys/select.h> |
||
9 | #include <ctype.h> |
||
10 | #include <errno.h> |
||
11 | #include <unistd.h> |
||
12 | #include <string.h> |
||
13 | #include <stdlib.h> |
||
14 | #include <stdio.h> |
||
15 | |||
16 | #include "includes/ConnectionPool.h" |
||
17 | #include "includes/client.h" |
||
18 | #include "../lib/colonet_defs.h" |
||
19 | 118 | emarinel | #include <colonet_wireless.h> |
20 | 11 | emarinel | |
21 | 29 | jknichel | /**
|
22 | * @brief The default constructor for ConnectionPool
|
||
23 | */
|
||
24 | 11 | emarinel | ConnectionPool::ConnectionPool() { |
25 | max_file_descriptor = 0;
|
||
26 | next_available_slot = 0;
|
||
27 | number_clients_ready = 0;
|
||
28 | |||
29 | FD_ZERO(&ready_set); |
||
30 | FD_ZERO(&read_set); |
||
31 | FD_ZERO(&write_set); |
||
32 | |||
33 | memset(&client_file_descriptor_array, 0, sizeof(int)*MAX_CONNECTIONS); |
||
34 | memset(&read_buffer, 0, sizeof(char *)*MAX_CONNECTIONS); |
||
35 | memset(&read_buffer_size, 0, sizeof(int)*MAX_CONNECTIONS); |
||
36 | memset(&write_buffer, 0, sizeof(char *)*MAX_CONNECTIONS); |
||
37 | memset(&write_buffer_size, 0, sizeof(int)*MAX_CONNECTIONS); |
||
38 | } |
||
39 | |||
40 | 29 | jknichel | /**
|
41 | * @brief The destructor for ConnectionPool
|
||
42 | */
|
||
43 | 11 | emarinel | ConnectionPool::~ConnectionPool() { |
44 | } |
||
45 | |||
46 | 29 | jknichel | /**
|
47 | * @brief Adds a client to the connection pool
|
||
48 | *
|
||
49 | * @param client_file_descriptor The file descriptor to add to the connection pool
|
||
50 | *
|
||
51 | * @return 0 on success, negative error code on failure
|
||
52 | */
|
||
53 | 11 | emarinel | int ConnectionPool::add_client(int client_file_descriptor) { |
54 | if (client_file_descriptor < 0) { |
||
55 | return ERROR_INVALID_CLIENT_DESCRIPTOR;
|
||
56 | } |
||
57 | |||
58 | if (next_available_slot == MAX_CONNECTIONS) {
|
||
59 | return ERROR_TOO_MANY_CLIENTS;
|
||
60 | } |
||
61 | |||
62 | if (client_file_descriptor > max_file_descriptor) {
|
||
63 | max_file_descriptor = client_file_descriptor; |
||
64 | } |
||
65 | |||
66 | FD_SET(client_file_descriptor, &ready_set); |
||
67 | |||
68 | int next_slot = next_available_slot;
|
||
69 | |||
70 | client_file_descriptor_array[next_slot] = client_file_descriptor; |
||
71 | read_buffer[next_slot] = (char*) malloc(sizeof(char) * READ_BUFFER_SIZE); |
||
72 | if (!(read_buffer[next_slot])) {
|
||
73 | return ERROR_ALLOCATING_MEMORY;
|
||
74 | } |
||
75 | read_buffer_size[next_slot] = 0;
|
||
76 | write_buffer[next_slot] = (char *)malloc(sizeof(char) * WRITE_BUFFER_SIZE); |
||
77 | |||
78 | if (!(write_buffer[next_slot])) {
|
||
79 | free(read_buffer[next_slot]); |
||
80 | return ERROR_ALLOCATING_MEMORY;
|
||
81 | } |
||
82 | |||
83 | write_buffer_size[next_slot] = 0;
|
||
84 | |||
85 | next_available_slot++; |
||
86 | |||
87 | return 0; |
||
88 | } |
||
89 | |||
90 | 29 | jknichel | /**
|
91 | * @brief Removes a client from the connection pool
|
||
92 | *
|
||
93 | * @param The index in the pool of the client to remove
|
||
94 | *
|
||
95 | * @return 0 on success, negative error code on failure
|
||
96 | */
|
||
97 | 27 | jknichel | int ConnectionPool::remove_client(int pool_index) { |
98 | if (pool_index < 0 || pool_index >= next_available_slot) { |
||
99 | 11 | emarinel | return ERROR_INVALID_CLIENT_DESCRIPTOR;
|
100 | } |
||
101 | |||
102 | 27 | jknichel | int client_file_descriptor = client_file_descriptor_array[pool_index];
|
103 | 11 | emarinel | |
104 | 27 | jknichel | if (FD_ISSET(client_file_descriptor, &ready_set)) {
|
105 | FD_CLR(client_file_descriptor, &ready_set); |
||
106 | 11 | emarinel | } |
107 | 27 | jknichel | if (FD_ISSET(client_file_descriptor, &read_set)) {
|
108 | FD_CLR(client_file_descriptor, &read_set); |
||
109 | 11 | emarinel | } |
110 | 27 | jknichel | if (FD_ISSET(client_file_descriptor, &write_set)) {
|
111 | FD_CLR(client_file_descriptor, &write_set); |
||
112 | 11 | emarinel | } |
113 | |||
114 | 27 | jknichel | free(read_buffer[pool_index]); |
115 | free(write_buffer[pool_index]); |
||
116 | for (int j = pool_index; j < next_available_slot - 1; j++) { |
||
117 | client_file_descriptor_array[pool_index] = client_file_descriptor_array[pool_index+1];
|
||
118 | read_buffer[pool_index] = read_buffer[pool_index+1];
|
||
119 | read_buffer_size[pool_index] = read_buffer_size[pool_index+1];
|
||
120 | write_buffer[pool_index] = write_buffer[pool_index+1];
|
||
121 | write_buffer_size[pool_index] = write_buffer_size[pool_index+1];
|
||
122 | 11 | emarinel | } |
123 | next_available_slot--; |
||
124 | int temp_max_file_descriptor = 0; |
||
125 | |||
126 | for (int j = 0; j < next_available_slot; j++) { |
||
127 | if (client_file_descriptor_array[j] > temp_max_file_descriptor)
|
||
128 | temp_max_file_descriptor = client_file_descriptor_array[j]; |
||
129 | } |
||
130 | max_file_descriptor = temp_max_file_descriptor; |
||
131 | |||
132 | printf("Removing client.\n");
|
||
133 | |||
134 | return 0; |
||
135 | } |
||
136 | |||
137 | 29 | jknichel | /**
|
138 | * @brief Checks the status of the clients
|
||
139 | *
|
||
140 | * Sees is any clients are ready to read from their file descriptor or are
|
||
141 | * ready to write to their file descriptor.
|
||
142 | *
|
||
143 | * @return 0 on success, negative error code on error
|
||
144 | */
|
||
145 | 11 | emarinel | //TODO: test that it drops commands properly if it gets sent too much data
|
146 | // do we want it to drop the data or drop the connection?
|
||
147 | 118 | emarinel | int ConnectionPool::check_clients() {
|
148 | 27 | jknichel | char temporary_buffer[READ_BUFFER_SIZE];
|
149 | char temporary_command_buffer[READ_BUFFER_SIZE+1]; |
||
150 | 11 | emarinel | int i;
|
151 | int client_file_descriptor;
|
||
152 | 27 | jknichel | int num_bytes_read;
|
153 | int length;
|
||
154 | 11 | emarinel | int sent;
|
155 | 27 | jknichel | int command_length;
|
156 | 11 | emarinel | |
157 | for (i = 0; i < next_available_slot; i++) { |
||
158 | client_file_descriptor = client_file_descriptor_array[i]; |
||
159 | |||
160 | if (FD_ISSET(client_file_descriptor, &read_set)) {
|
||
161 | 27 | jknichel | num_bytes_read = read(client_file_descriptor, temporary_buffer, READ_BUFFER_SIZE); |
162 | 11 | emarinel | |
163 | 27 | jknichel | if (num_bytes_read == 0 || (num_bytes_read == -1 && errno == ECONNRESET)) { |
164 | 11 | emarinel | remove_client(i); |
165 | i--; |
||
166 | continue;
|
||
167 | } |
||
168 | |||
169 | 27 | jknichel | while (num_bytes_read > 0) { |
170 | length = num_bytes_read; |
||
171 | 11 | emarinel | |
172 | 27 | jknichel | if (length + read_buffer_size[i] > READ_BUFFER_SIZE) {
|
173 | length = READ_BUFFER_SIZE - read_buffer_size[i]; |
||
174 | 11 | emarinel | } |
175 | |||
176 | 27 | jknichel | memcpy(read_buffer[i]+read_buffer_size[i], temporary_buffer, length); |
177 | read_buffer_size[i] += length; |
||
178 | num_bytes_read -= length; |
||
179 | 11 | emarinel | |
180 | 27 | jknichel | if (num_bytes_read > 0) { |
181 | memmove(temporary_buffer, temporary_buffer+length, READ_BUFFER_SIZE - length); |
||
182 | 11 | emarinel | } |
183 | |||
184 | printf("Read buffer is %s\n", read_buffer[i]);
|
||
185 | |||
186 | 27 | jknichel | char* newline_position;
|
187 | 11 | emarinel | |
188 | 27 | jknichel | while ((newline_position = strstr(read_buffer[i], "\n"))) { |
189 | 11 | emarinel | |
190 | //if no newline if found in the entire readbuffer (when its full),
|
||
191 | //toss out the command
|
||
192 | // because either the command being given is too long or someone is trying
|
||
193 | // to do something bad to the server
|
||
194 | //TODO: this is from before all this code was put in the loop. reconsider
|
||
195 | // how to check this error condition and do it elsewhere
|
||
196 | 27 | jknichel | if (!newline_position && (read_buffer_size[i] == READ_BUFFER_SIZE)) {
|
197 | 11 | emarinel | read_buffer_size[i] = 0;
|
198 | break;
|
||
199 | } |
||
200 | |||
201 | //if no newline is found then there is not a command in the buffer
|
||
202 | 27 | jknichel | if (!newline_position) {
|
203 | 11 | emarinel | break;
|
204 | } |
||
205 | |||
206 | 27 | jknichel | command_length = (newline_position - read_buffer[i])+1;
|
207 | 11 | emarinel | |
208 | //the newline was found in garbage in the currently not used portion
|
||
209 | // of the read buffer
|
||
210 | 27 | jknichel | if (command_length > read_buffer_size[i]) {
|
211 | 11 | emarinel | break;
|
212 | } |
||
213 | |||
214 | 27 | jknichel | memcpy(temporary_command_buffer, read_buffer[i], command_length); |
215 | //do command_length-1 to get rid of the newline terminating the command
|
||
216 | temporary_command_buffer[command_length-1] = '\0'; |
||
217 | 11 | emarinel | //did this because telnet was putting a \r\n on the end instead of just \n
|
218 | 27 | jknichel | if (isspace(temporary_command_buffer[command_length-2])) { |
219 | temporary_command_buffer[command_length-2] = '\0'; |
||
220 | 11 | emarinel | } |
221 | |||
222 | 27 | jknichel | memmove(read_buffer[i], read_buffer[i]+command_length, read_buffer_size[i] - command_length); |
223 | read_buffer_size[i] -= command_length; |
||
224 | 11 | emarinel | |
225 | 27 | jknichel | if (command_length > MAX_COMMAND_LEN) {
|
226 | 11 | emarinel | printf("The command was too long. Tossing command out.\n");
|
227 | break;
|
||
228 | } |
||
229 | |||
230 | 118 | emarinel | if (parse_command(temporary_command_buffer, i) < 0) { |
231 | 11 | emarinel | printf("There was an error parsing command\n");
|
232 | break;
|
||
233 | } |
||
234 | } |
||
235 | } |
||
236 | } |
||
237 | |||
238 | if (FD_ISSET(client_file_descriptor, &write_set)) {
|
||
239 | if (write_buffer_size[i] == 0) { |
||
240 | continue;
|
||
241 | } |
||
242 | |||
243 | sent = write(client_file_descriptor, write_buffer[i], write_buffer_size[i]); |
||
244 | memmove(write_buffer[i], write_buffer[i]+sent, WRITE_BUFFER_SIZE - sent); |
||
245 | write_buffer_size[i] -= sent; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | return 0; |
||
250 | } |
||
251 | |||
252 | 29 | jknichel | /**
|
253 | * @brief Puts text into a write buffer that will be written to a client's file
|
||
254 | * descriptor sometime when the client is ready to write.
|
||
255 | *
|
||
256 | * @param pool_index Index in the pool of the client to write to
|
||
257 | * @param message The message to be written
|
||
258 | * @param length The length of the message
|
||
259 | *
|
||
260 | * @return 0 on success, negative error code on failure
|
||
261 | */
|
||
262 | 14 | jknichel | int ConnectionPool::write_to_client(int pool_index, char * message, int length) { |
263 | 22 | jknichel | if (pool_index < 0 || pool_index >= next_available_slot) { |
264 | return ERROR_INVALID_CLIENT_ID;
|
||
265 | } |
||
266 | |||
267 | if (!message) {
|
||
268 | return ERROR_INVALID_MESSAGE;
|
||
269 | } |
||
270 | |||
271 | if (length < 0) { |
||
272 | return ERROR_INVALID_MESSAGE_LENGTH;
|
||
273 | } |
||
274 | |||
275 | 34 | emarinel | if (length > (WRITE_BUFFER_SIZE-write_buffer_size[pool_index])) {
|
276 | //TODO: make this a logging statement instead of a print statement
|
||
277 | printf("There is not enough room in the write buffer to send the data to the client.\n");
|
||
278 | return ERROR_NOT_ENOUGH_ROOM;
|
||
279 | } |
||
280 | 11 | emarinel | |
281 | 14 | jknichel | memcpy(write_buffer[pool_index], message, length); |
282 | write_buffer_size[pool_index] += length; |
||
283 | |||
284 | return 0; |
||
285 | } |
||
286 | |||
287 | 29 | jknichel | /**
|
288 | * @brief Sets the socket to listen on
|
||
289 | *
|
||
290 | * @param listen_socket The socket to listen on
|
||
291 | *
|
||
292 | * @return void
|
||
293 | */
|
||
294 | 11 | emarinel | void ConnectionPool::set_listen_socket_in_ready_set(int listen_socket) { |
295 | 58 | jknichel | if (listen_socket < 0) |
296 | return;
|
||
297 | |||
298 | 11 | emarinel | FD_SET(listen_socket, &ready_set); |
299 | } |
||
300 | |||
301 | 29 | jknichel | /**
|
302 | * @brief Find out what file descriptors are ready to write to and read from
|
||
303 | *
|
||
304 | * @param listen_socket The socket to listen on
|
||
305 | * @param select_timeout The timeout for the select statement
|
||
306 | *
|
||
307 | * @return 0
|
||
308 | */
|
||
309 | 58 | jknichel | int ConnectionPool::perform_select(int listen_socket) { |
310 | 11 | emarinel | read_set = ready_set; |
311 | write_set = ready_set; |
||
312 | |||
313 | 58 | jknichel | struct timeval select_timeout;
|
314 | memset(&select_timeout, 0, sizeof(select_timeout)); |
||
315 | |||
316 | 11 | emarinel | //TODO(Jason): think about why I put this there
|
317 | if (max_file_descriptor < listen_socket)
|
||
318 | max_file_descriptor = listen_socket; |
||
319 | |||
320 | 58 | jknichel | number_clients_ready = select(max_file_descriptor+1, &(read_set), &(write_set), NULL, &select_timeout); |
321 | 11 | emarinel | |
322 | 59 | jknichel | if (number_clients_ready < 0) { |
323 | perror(__FUNCTION__); |
||
324 | } |
||
325 | |||
326 | 11 | emarinel | return 0; |
327 | } |
||
328 | |||
329 | int ConnectionPool::is_socket_ready_to_read(int socket) { |
||
330 | return FD_ISSET(socket, &read_set);
|
||
331 | } |
||
332 | |||
333 | int ConnectionPool::is_socket_ready_to_write(int socket) { |
||
334 | return FD_ISSET(socket, &write_set);
|
||
335 | } |
||
336 | |||
337 | int ConnectionPool::get_max_file_descriptor() {
|
||
338 | return max_file_descriptor;
|
||
339 | } |
||
340 | |||
341 | void ConnectionPool::set_max_file_descriptor(int new_max_file_descriptor) { |
||
342 | max_file_descriptor = new_max_file_descriptor; |
||
343 | } |
||
344 | |||
345 | int ConnectionPool::get_next_available_slot() {
|
||
346 | return next_available_slot;
|
||
347 | } |
||
348 | |||
349 | int ConnectionPool::get_number_clients_ready() {
|
||
350 | return number_clients_ready;
|
||
351 | } |
||
352 | |||
353 | void ConnectionPool::set_number_clients_ready(int new_number_clients_ready) { |
||
354 | number_clients_ready = new_number_clients_ready; |
||
355 | } |
||
356 | |||
357 | fd_set ConnectionPool::get_ready_set() { |
||
358 | return ready_set;
|
||
359 | } |
||
360 | |||
361 | fd_set ConnectionPool::get_read_set() { |
||
362 | return read_set;
|
||
363 | } |
||
364 | |||
365 | void ConnectionPool::set_read_set(fd_set new_set) {
|
||
366 | read_set = new_set; |
||
367 | } |
||
368 | |||
369 | fd_set ConnectionPool::get_write_set() { |
||
370 | return write_set;
|
||
371 | } |
||
372 | |||
373 | void ConnectionPool::set_write_set(fd_set new_set) {
|
||
374 | write_set = new_set; |
||
375 | } |
||
376 | |||
377 | 123 | jknichel | //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 | 58 | jknichel | //TODO: write a function to write data into the write buffers (jason: what was this referring to?)
|
381 | 118 | emarinel | int ConnectionPool::parse_command(char* command, int pool_index) { |
382 | 11 | emarinel | char tokens[MAX_TOKENS][MAX_TOKEN_SIZE];
|
383 | 56 | jknichel | unsigned char int_tokens[MAX_TOKENS]; |
384 | 58 | jknichel | int number_tokens = 0; |
385 | char* end_pointer = NULL; |
||
386 | int command_id;
|
||
387 | 11 | emarinel | int i;
|
388 | 58 | jknichel | unsigned char arguments[PACKET_DATA_LEN]; |
389 | 11 | emarinel | |
390 | 58 | jknichel | memset(arguments, 1, PACKET_DATA_LEN);
|
391 | 11 | emarinel | |
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 | 58 | jknichel | if ((number_tokens = tokenize_command(command, tokens)) < 0) { |
405 | 11 | emarinel | return -1; |
406 | } |
||
407 | |||
408 | //the 10 in the function call indicates number is base 10
|
||
409 | 58 | jknichel | command_id = strtol(tokens[0], &end_pointer, 10); |
410 | 11 | emarinel | |
411 | 58 | jknichel | if (!end_pointer || *end_pointer != '\0') { |
412 | 11 | emarinel | printf("There was an error converting first token into a number.\n");
|
413 | return -1; |
||
414 | } |
||
415 | |||
416 | 68 | jknichel | if (command_id == SEND_TO_ROBOT) {
|
417 | 58 | jknichel | int number_int_tokens = number_tokens;
|
418 | 11 | emarinel | |
419 | 68 | jknichel | // Convert tokens to ints
|
420 | 58 | jknichel | for (i = ROBOT_COMMAND_OFFSET; i < number_int_tokens; i++) {
|
421 | 11 | emarinel | int_tokens[i-ROBOT_COMMAND_OFFSET] = atoi(tokens[i]); |
422 | } |
||
423 | 68 | jknichel | /* we removed the request from robot constant
|
424 | 58 | jknichel | if (command_id == REQUEST_FROM_ROBOT) {
|
425 | 11 | emarinel | 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 | 58 | jknichel | number_int_tokens++;
|
431 | 11 | emarinel | } 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 | 68 | jknichel | */
|
438 | 11 | emarinel | |
439 | 68 | jknichel | // Fill arguments buffer with arguments
|
440 | 118 | emarinel | for (i = ROBOT_COMMAND_LEN; i < number_int_tokens-ROBOT_COMMAND_OFFSET;
|
441 | i++) { |
||
442 | 58 | jknichel | arguments[i-ROBOT_COMMAND_LEN] = int_tokens[i]; |
443 | 11 | emarinel | } |
444 | |||
445 | 68 | jknichel | // Check the tokens
|
446 | 58 | jknichel | if (check_tokens(int_tokens, number_int_tokens) < 0) { |
447 | 11 | emarinel | fprintf(stderr, "%s: Error - Invalid command/request.\n", __FUNCTION__);
|
448 | return 0; |
||
449 | } |
||
450 | |||
451 | 68 | jknichel | // Send packet to robot
|
452 | 118 | emarinel | fprintf(stderr, "Calling colonet_wl_send(%d, %d, %d, arguments)\n",
|
453 | 11 | emarinel | int_tokens[0], int_tokens[1], int_tokens[2]); |
454 | 118 | emarinel | colonet_wl_send(pool_index, int_tokens[0],
|
455 | (ColonetMessageType)int_tokens[1], int_tokens[2], |
||
456 | arguments); |
||
457 | 68 | jknichel | } else if (command_id == REQUEST_FROM_SERVER) { |
458 | 75 | jknichel | if (number_tokens < 2) |
459 | return -1; |
||
460 | |||
461 | end_pointer=NULL;
|
||
462 | int second_token = strtol(tokens[1], &end_pointer, 10); |
||
463 | |||
464 | if (!end_pointer || *end_pointer != '\0') { |
||
465 | printf("There was an error converting second token into a number.\n");
|
||
466 | return -1; |
||
467 | } |
||
468 | |||
469 | 123 | jknichel | //TODO: move REQUEST_BOM_MATRIX stuff into a private function
|
470 | 75 | jknichel | if (second_token == REQUEST_BOM_MATRIX) {
|
471 | //TODO: rename to indicate its actually the response message
|
||
472 | char bom_matrix_buffer[MAX_RESPONSE_LEN];
|
||
473 | char temp_bom_matrix_buffer[MAX_RESPONSE_LEN];
|
||
474 | |||
475 | //TODO: change after we start keeping track of bom matrix
|
||
476 | int number_robots = rand()%10; |
||
477 | int bom_matrix[number_robots][number_robots];
|
||
478 | for (int ii = 0; ii < number_robots; ii++) { |
||
479 | for (int j = 0; j < number_robots; j++) { |
||
480 | //do this to generate some -1 values which mean they can't see each other
|
||
481 | int matrix_value = rand()%(number_robots+1)-1; |
||
482 | bom_matrix[ii][j] = matrix_value; |
||
483 | } |
||
484 | } |
||
485 | |||
486 | printf("number of robots is %d\n", number_robots);
|
||
487 | |||
488 | //TODO: separate parameters with spaces
|
||
489 | //TODO: make this better
|
||
490 | //TODO: make sure I don't need to do MAX_RESPONSE_LENGTH-1
|
||
491 | snprintf(bom_matrix_buffer,MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_BOM_MATRIX, number_robots);
|
||
492 | for (int ii = 0; ii < number_robots; ii++) { |
||
493 | for (int j = 0; j < number_robots; j++) { |
||
494 | //TODO: don't use strcpy
|
||
495 | strcpy(temp_bom_matrix_buffer, bom_matrix_buffer); |
||
496 | //TODO: put length checking in here so array doesn't go out of bounds
|
||
497 | //TODO: maybe use strncat?
|
||
498 | strcat(temp_bom_matrix_buffer," %d");
|
||
499 | snprintf(bom_matrix_buffer, MAX_RESPONSE_LEN, temp_bom_matrix_buffer, bom_matrix[ii][j]); |
||
500 | } |
||
501 | } |
||
502 | strcat(bom_matrix_buffer,"\n");
|
||
503 | write_to_client(pool_index, bom_matrix_buffer, strlen(bom_matrix_buffer)); |
||
504 | printf("Sending %s", bom_matrix_buffer);
|
||
505 | 123 | jknichel | } else if (second_token == REQUEST_XBEE_IDS) { |
506 | //TODO: move this into private function
|
||
507 | //TODO: make this better
|
||
508 | int number_robots = rand() % 10; |
||
509 | |||
510 | char xbee_id_buffer[MAX_RESPONSE_LEN];
|
||
511 | char temp_xbee_id_buffer[MAX_RESPONSE_LEN];
|
||
512 | |||
513 | snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_XBEE_IDS, number_robots);
|
||
514 | |||
515 | printf("number of robots is %d\n", number_robots);
|
||
516 | |||
517 | for (int ii = 0; ii < number_robots; ii++) { |
||
518 | strcpy(temp_xbee_id_buffer, xbee_id_buffer); |
||
519 | //TODO: put length checking in here so array doesn't go out of bounds
|
||
520 | //TODO: maybe use strncat?
|
||
521 | strcat(temp_xbee_id_buffer, " %d");
|
||
522 | snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, temp_xbee_id_buffer, ii); |
||
523 | } |
||
524 | strcat(xbee_id_bufer, "\n");
|
||
525 | write_to_client(pool_index, xbee_id_buffer, strlen(xbee_id_buffer)); |
||
526 | printf("Sending %s", xbee_id_buffer);
|
||
527 | 75 | jknichel | } else {
|
528 | char * my_current_message = "Hi, how are you?\n"; |
||
529 | printf("Sending %s\n", my_current_message);
|
||
530 | write_to_client(pool_index, my_current_message, strlen(my_current_message)); |
||
531 | } |
||
532 | 11 | emarinel | } |
533 | |||
534 | return 0; |
||
535 | } |
||
536 | |||
537 | 55 | jknichel | /**
|
538 | * @brief Breaks a command up into tokens
|
||
539 | *
|
||
540 | * @param command The command to tokenize
|
||
541 | * @param tokens A two dimensional character array to store the tokens in
|
||
542 | *
|
||
543 | * @return 0 on success, negative error code on failure
|
||
544 | */
|
||
545 | 11 | emarinel | int ConnectionPool::tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]) { |
546 | 58 | jknichel | char* next_token = command;
|
547 | char* end_token = NULL; |
||
548 | int number_tokens = 0; |
||
549 | 11 | emarinel | |
550 | if (!command) {
|
||
551 | return -1; |
||
552 | } |
||
553 | |||
554 | 58 | jknichel | while ((end_token = strstr(next_token, " "))) { |
555 | *end_token = '\0';
|
||
556 | 11 | emarinel | |
557 | 58 | jknichel | if (strlen(next_token) > MAX_TOKEN_SIZE-1) { |
558 | 11 | emarinel | return -1; |
559 | } |
||
560 | |||
561 | 58 | jknichel | strcpy(tokens[number_tokens], next_token); |
562 | 11 | emarinel | |
563 | 58 | jknichel | number_tokens++; |
564 | next_token = end_token + 1;
|
||
565 | 11 | emarinel | |
566 | 58 | jknichel | while (isspace(*next_token) && *next_token != '\0') { |
567 | next_token++; |
||
568 | 11 | emarinel | } |
569 | } |
||
570 | |||
571 | 58 | jknichel | if (end_token == NULL && *next_token != '\0') { |
572 | if (strlen(next_token) > MAX_TOKEN_SIZE-1) { |
||
573 | 11 | emarinel | return -1; |
574 | } |
||
575 | |||
576 | 58 | jknichel | strcpy(tokens[number_tokens], next_token); |
577 | 11 | emarinel | |
578 | 58 | jknichel | number_tokens++; |
579 | 11 | emarinel | } |
580 | |||
581 | 58 | jknichel | return number_tokens;
|
582 | 11 | emarinel | } |
583 | |||
584 | 55 | jknichel | /**
|
585 | * @brief checks a list of tokens to see if it's valid
|
||
586 | 11 | emarinel | *
|
587 | 55 | jknichel | * @param tokens The tokens to check
|
588 | 58 | jknichel | * @param number_tokens The number of tokens contained in the tokens parameter
|
589 | 55 | jknichel | *
|
590 | 11 | emarinel | * @return 0 if tokens is valid
|
591 | */
|
||
592 | 58 | jknichel | int ConnectionPool::check_tokens(unsigned char* tokens, int number_tokens) { |
593 | if (number_tokens > 3 + PACKET_DATA_LEN) { |
||
594 | 11 | emarinel | /* Too many tokens */
|
595 | return -1; |
||
596 | } |
||
597 | |||
598 | 58 | jknichel | if (number_tokens < 3) { |
599 | 11 | emarinel | /* Not enough tokens */
|
600 | return -1; |
||
601 | } |
||
602 | |||
603 | if (tokens[1] != COLONET_REQUEST && tokens[1] != COLONET_COMMAND) { |
||
604 | /* Invalid message type */
|
||
605 | return -1; |
||
606 | } |
||
607 | |||
608 | return 0; |
||
609 | } |