Revision 642
added more comments
ConnectionPool.cpp | ||
---|---|---|
22 | 22 |
|
23 | 23 |
/** |
24 | 24 |
* @brief The default constructor for ConnectionPool |
25 |
* |
|
26 |
* @param cs The colonet server instance to use with this class |
|
25 | 27 |
*/ |
26 | 28 |
ConnectionPool::ConnectionPool(ColonetServer* cs) { |
27 | 29 |
colonet_server = cs; |
... | ... | |
67 | 69 |
max_file_descriptor = client_file_descriptor; |
68 | 70 |
} |
69 | 71 |
|
72 |
//add the new file descriptor to the set of ready descriptors |
|
70 | 73 |
FD_SET(client_file_descriptor, &ready_set); |
71 | 74 |
|
72 | 75 |
int next_slot = next_available_slot; |
73 | 76 |
|
77 |
//put the new client into the connection pool |
|
74 | 78 |
client_file_descriptor_array[next_slot] = client_file_descriptor; |
75 | 79 |
read_buffer[next_slot] = (char*) malloc(sizeof(char) * READ_BUFFER_SIZE); |
76 | 80 |
if (!(read_buffer[next_slot])) { |
77 | 81 |
return ERROR_ALLOCATING_MEMORY; |
78 | 82 |
} |
79 | 83 |
read_buffer_size[next_slot] = 0; |
84 |
|
|
80 | 85 |
write_buffer[next_slot] = (char *)malloc(sizeof(char) * WRITE_BUFFER_SIZE); |
81 |
|
|
82 | 86 |
if (!(write_buffer[next_slot])) { |
83 | 87 |
free(read_buffer[next_slot]); |
84 | 88 |
return ERROR_ALLOCATING_MEMORY; |
85 | 89 |
} |
86 |
|
|
87 | 90 |
write_buffer_size[next_slot] = 0; |
88 | 91 |
|
89 | 92 |
next_available_slot++; |
... | ... | |
105 | 108 |
|
106 | 109 |
int client_file_descriptor = client_file_descriptor_array[pool_index]; |
107 | 110 |
|
111 |
//clear this client from all lists of file descriptors |
|
108 | 112 |
if (FD_ISSET(client_file_descriptor, &ready_set)) { |
109 | 113 |
FD_CLR(client_file_descriptor, &ready_set); |
110 | 114 |
} |
... | ... | |
115 | 119 |
FD_CLR(client_file_descriptor, &write_set); |
116 | 120 |
} |
117 | 121 |
|
122 |
//free up the resources this client used |
|
118 | 123 |
free(read_buffer[pool_index]); |
119 | 124 |
free(write_buffer[pool_index]); |
125 |
|
|
126 |
//shift the other clients down |
|
120 | 127 |
for (int j = pool_index; j < next_available_slot - 1; j++) { |
121 | 128 |
client_file_descriptor_array[pool_index] = client_file_descriptor_array[pool_index+1]; |
122 | 129 |
read_buffer[pool_index] = read_buffer[pool_index+1]; |
... | ... | |
127 | 134 |
next_available_slot--; |
128 | 135 |
int temp_max_file_descriptor = 0; |
129 | 136 |
|
137 |
//figure out the newest max file descriptor |
|
130 | 138 |
for (int j = 0; j < next_available_slot; j++) { |
131 | 139 |
if (client_file_descriptor_array[j] > temp_max_file_descriptor) |
132 | 140 |
temp_max_file_descriptor = client_file_descriptor_array[j]; |
... | ... | |
154 | 162 |
for (i = 0; i < next_available_slot; i++) { |
155 | 163 |
int client_file_descriptor = client_file_descriptor_array[i]; |
156 | 164 |
|
165 |
//check to see if this client is ready to be read from |
|
157 | 166 |
if (FD_ISSET(client_file_descriptor, &read_set)) { |
158 | 167 |
if (read_data(i, client_file_descriptor) == DECREMENT_INDEX_COUNTER) { |
159 |
i--; |
|
160 |
continue; |
|
168 |
i--;
|
|
169 |
continue;
|
|
161 | 170 |
} |
162 | 171 |
} |
163 | 172 |
|
173 |
//check to see if this client is ready to write to |
|
164 | 174 |
if (FD_ISSET(client_file_descriptor, &write_set)) { |
165 | 175 |
write_data(i, client_file_descriptor); |
166 | 176 |
} |
... | ... | |
243 | 253 |
if (max_file_descriptor < listen_socket) |
244 | 254 |
max_file_descriptor = listen_socket; |
245 | 255 |
|
256 |
//call select. select sees if any file descriptor in the read set is ready to be read and modifies the read set. |
|
257 |
// It sees if any file descriptor in the write set is ready to be written to and modifies the write set. |
|
246 | 258 |
number_clients_ready = select(max_file_descriptor+1, &(read_set), &(write_set), NULL, &select_timeout); |
247 | 259 |
|
248 | 260 |
if (number_clients_ready < 0) { |
... | ... | |
252 | 264 |
return 0; |
253 | 265 |
} |
254 | 266 |
|
267 |
/** |
|
268 |
* @return 1 if the socket is ready to be read, 0 otherwise |
|
269 |
*/ |
|
255 | 270 |
int ConnectionPool::is_socket_ready_to_read(int socket) { |
256 | 271 |
return FD_ISSET(socket, &read_set); |
257 | 272 |
} |
258 | 273 |
|
274 |
/** |
|
275 |
* @return the number of clients that are ready |
|
276 |
*/ |
|
259 | 277 |
int ConnectionPool::get_number_clients_ready() { |
260 | 278 |
return number_clients_ready; |
261 | 279 |
} |
262 | 280 |
|
263 | 281 |
/** |
264 |
*/ |
|
282 |
* @brief Reads data from a particular client and checks to see if it contains a command and parses that command |
|
283 |
* or buffers the data assuming the rest of the command will be sent later |
|
284 |
* |
|
285 |
* @param pool_index The index in the connection pool of the client to read from |
|
286 |
* @param client_file_descriptor The file descriptor of the client to read from |
|
287 |
* |
|
288 |
* @return 0 on success, negative error code on error |
|
289 |
*/ |
|
265 | 290 |
int ConnectionPool::read_data(int pool_index, int client_file_descriptor) { |
266 | 291 |
char temporary_buffer[READ_BUFFER_SIZE]; |
267 | 292 |
char temporary_command_buffer[READ_BUFFER_SIZE+1]; |
... | ... | |
269 | 294 |
int length; |
270 | 295 |
int command_length; |
271 | 296 |
|
297 |
//read data that the client is trying to send us |
|
272 | 298 |
num_bytes_read = read(client_file_descriptor, temporary_buffer, READ_BUFFER_SIZE); |
273 | 299 |
|
300 |
//check to see if the client disconnected |
|
274 | 301 |
if (num_bytes_read == 0 || (num_bytes_read == -1 && errno == ECONNRESET)) { |
275 | 302 |
remove_client(pool_index); |
276 | 303 |
return DECREMENT_INDEX_COUNTER; |
277 | 304 |
} |
278 | 305 |
|
306 |
|
|
279 | 307 |
while (num_bytes_read > 0) { |
280 | 308 |
length = num_bytes_read; |
281 | 309 |
|
310 |
//make sure this new data won't overflow the read buffer |
|
282 | 311 |
if (length + read_buffer_size[pool_index] > READ_BUFFER_SIZE) { |
283 | 312 |
length = READ_BUFFER_SIZE - read_buffer_size[pool_index]; |
284 | 313 |
} |
285 | 314 |
|
315 |
//put the newly read data into the read buffer for this client |
|
286 | 316 |
memcpy(read_buffer[pool_index]+read_buffer_size[pool_index], temporary_buffer, length); |
287 | 317 |
read_buffer_size[pool_index] += length; |
288 | 318 |
num_bytes_read -= length; |
... | ... | |
291 | 321 |
memmove(temporary_buffer, temporary_buffer+length, READ_BUFFER_SIZE - length); |
292 | 322 |
} |
293 | 323 |
|
294 |
//printf("read_data: Read buffer is %s\n", read_buffer[pool_index]); |
|
295 |
|
|
296 | 324 |
char* newline_position; |
297 | 325 |
|
298 | 326 |
while ((newline_position = strstr(read_buffer[pool_index], "\n"))) { |
299 |
|
|
300 |
//if no newline if found in the entire readbuffer (when its full), |
|
301 |
//toss out the command |
|
327 |
//if no newline is found in the entire readbuffer (when its full), |
|
328 |
// toss out the command |
|
302 | 329 |
// because either the command being given is too long or someone is trying |
303 | 330 |
// to do something bad to the server |
304 | 331 |
//TODO: this is from before all this code was put in the loop. reconsider |
... | ... | |
348 | 375 |
return 0; |
349 | 376 |
} |
350 | 377 |
|
378 |
/** |
|
379 |
* @brief This function takes data out of the write buffer for a client and tries to actually send it to the client |
|
380 |
* |
|
381 |
* @param pool_index The index in the connection pool of the client to write to |
|
382 |
* @param client_file_descriptor The file descriptor to write out on |
|
383 |
* |
|
384 |
* @return 0 on success, negative error code on failure |
|
385 |
*/ |
|
351 | 386 |
int ConnectionPool::write_data(int pool_index, int client_file_descriptor) { |
352 | 387 |
if (write_buffer_size[pool_index] == 0) { |
353 | 388 |
return 0; |
Also available in: Unified diff