00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <socket_core.h>
00038 #include <packet_client.h>
00039 #include <packet_remote.h>
00040
00041 #include <net/socket_codes.h>
00042 #include <net/in.h>
00043 #include <net/inet.h>
00044 #include <net/packet.h>
00045 #include <net/modules.h>
00046
00047 #include <stdint.h>
00048 #include <stdlib.h>
00049 #include <errno.h>
00050
00051 #include <adt/dynamic_fifo.h>
00052 #include <adt/int_map.h>
00053
00058 #define SOCKET_ID_TRIES 100
00059
00061 struct socket_port {
00063 socket_port_map_t map;
00065 int count;
00066 };
00067
00068 INT_MAP_IMPLEMENT(socket_cores, socket_core_t);
00069
00070 GENERIC_CHAR_MAP_IMPLEMENT(socket_port_map, socket_core_t *);
00071
00072 INT_MAP_IMPLEMENT(socket_ports, socket_port_t);
00073
00086 static void
00087 socket_destroy_core(int packet_phone, socket_core_t *socket,
00088 socket_cores_t *local_sockets, socket_ports_t *global_sockets,
00089 void (* socket_release)(socket_core_t *socket))
00090 {
00091 int packet_id;
00092
00093
00094 if (socket->port) {
00095
00096 socket_port_release(global_sockets, socket);
00097 }
00098
00099
00100 while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0)
00101 pq_release_remote(packet_phone, packet_id);
00102
00103 dyn_fifo_destroy(&socket->received);
00104 dyn_fifo_destroy(&socket->accepted);
00105
00106 if (socket_release)
00107 socket_release(socket);
00108
00109 socket_cores_exclude(local_sockets, socket->socket_id, free);
00110 }
00111
00122 void
00123 socket_cores_release(int packet_phone, socket_cores_t *local_sockets,
00124 socket_ports_t *global_sockets,
00125 void (* socket_release)(socket_core_t *socket))
00126 {
00127 int index;
00128
00129 if (!socket_cores_is_valid(local_sockets))
00130 return;
00131
00132 local_sockets->magic = 0;
00133
00134 for (index = 0; index < local_sockets->next; ++index) {
00135 if (socket_cores_item_is_valid(&local_sockets->items[index])) {
00136 local_sockets->items[index].magic = 0;
00137
00138 if (local_sockets->items[index].value) {
00139 socket_destroy_core(packet_phone,
00140 local_sockets->items[index].value,
00141 local_sockets, global_sockets,
00142 socket_release);
00143 free(local_sockets->items[index].value);
00144 local_sockets->items[index].value = NULL;
00145 }
00146 }
00147 }
00148
00149 free(local_sockets->items);
00150 }
00151
00161 static int
00162 socket_port_add_core(socket_port_t *socket_port, socket_core_t *socket,
00163 const uint8_t *key, size_t key_length)
00164 {
00165 socket_core_t **socket_ref;
00166 int rc;
00167
00168
00169 socket_ref = malloc(sizeof(*socket_ref));
00170 if (!socket_ref)
00171 return ENOMEM;
00172
00173 *socket_ref = socket;
00174
00175 rc = socket_port_map_add(&socket_port->map, key, key_length,
00176 socket_ref);
00177 if (rc != EOK) {
00178 free(socket_ref);
00179 return rc;
00180 }
00181
00182 ++socket_port->count;
00183 socket->key = key;
00184 socket->key_length = key_length;
00185
00186 return EOK;
00187 }
00188
00201 static int
00202 socket_bind_insert(socket_ports_t *global_sockets, socket_core_t *socket,
00203 int port)
00204 {
00205 socket_port_t *socket_port;
00206 int rc;
00207
00208
00209 socket_port = malloc(sizeof(*socket_port));
00210 if (!socket_port)
00211 return ENOMEM;
00212
00213 socket_port->count = 0;
00214 rc = socket_port_map_initialize(&socket_port->map);
00215 if (rc != EOK)
00216 goto fail;
00217
00218 rc = socket_port_add_core(socket_port, socket,
00219 (const uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
00220 if (rc != EOK)
00221 goto fail;
00222
00223
00224 rc = socket_ports_add(global_sockets, port, socket_port);
00225 if (rc < 0)
00226 goto fail;
00227
00228 socket->port = port;
00229 return EOK;
00230
00231 fail:
00232 socket_port_map_destroy(&socket_port->map, free);
00233 free(socket_port);
00234 return rc;
00235
00236 }
00237
00259 int
00260 socket_bind(socket_cores_t *local_sockets, socket_ports_t *global_sockets,
00261 int socket_id, void *addr, size_t addrlen, int free_ports_start,
00262 int free_ports_end, int last_used_port)
00263 {
00264 socket_core_t *socket;
00265 socket_port_t *socket_port;
00266 struct sockaddr *address;
00267 struct sockaddr_in *address_in;
00268
00269 if (addrlen < sizeof(struct sockaddr))
00270 return EINVAL;
00271
00272 address = (struct sockaddr *) addr;
00273 switch (address->sa_family) {
00274 case AF_INET:
00275 if (addrlen != sizeof(struct sockaddr_in))
00276 return EINVAL;
00277
00278 address_in = (struct sockaddr_in *) addr;
00279
00280 socket = socket_cores_find(local_sockets, socket_id);
00281 if (!socket)
00282 return ENOTSOCK;
00283
00284
00285 if (address_in->sin_port <= 0)
00286 return socket_bind_free_port(global_sockets, socket,
00287 free_ports_start, free_ports_end, last_used_port);
00288
00289
00290 socket_port = socket_ports_find(global_sockets,
00291 ntohs(address_in->sin_port));
00292 if (socket_port) {
00293
00294 return EADDRINUSE;
00295 }
00296
00297
00298 if (socket->port) {
00299
00300 socket_port_release(global_sockets, socket);
00301 }
00302 socket->port = -1;
00303
00304 return socket_bind_insert(global_sockets, socket,
00305 ntohs(address_in->sin_port));
00306
00307 case AF_INET6:
00308
00309 break;
00310 }
00311
00312 return EAFNOSUPPORT;
00313 }
00314
00329 int
00330 socket_bind_free_port(socket_ports_t *global_sockets, socket_core_t *socket,
00331 int free_ports_start, int free_ports_end, int last_used_port)
00332 {
00333 int index;
00334
00335
00336 index = last_used_port;
00337
00338 do {
00339 ++index;
00340
00341
00342 if (index >= free_ports_end) {
00343
00344 index = free_ports_start - 1;
00345 do {
00346 ++index;
00347
00348 if (index >= last_used_port) {
00349
00350 return ENOTCONN;
00351 }
00352 } while (socket_ports_find(global_sockets, index));
00353
00354
00355 break;
00356 }
00357
00358 } while (socket_ports_find(global_sockets, index));
00359
00360 return socket_bind_insert(global_sockets, socket, index);
00361 }
00362
00372 static int socket_generate_new_id(socket_cores_t *local_sockets, int positive)
00373 {
00374 int socket_id;
00375 int count;
00376
00377 count = 0;
00378 #if 0
00379 socket_id = socket_globals.last_id;
00380 #endif
00381 do {
00382 if (count < SOCKET_ID_TRIES) {
00383 socket_id = rand() % INT_MAX;
00384 ++count;
00385 } else if (count == SOCKET_ID_TRIES) {
00386 socket_id = 1;
00387 ++count;
00388
00389 } else {
00390 if (socket_id < INT_MAX) {
00391 ++ socket_id;
00392 #if 0
00393 } else if(socket_globals.last_id) {
00394 socket_globals.last_id = 0;
00395 socket_id = 1;
00396 #endif
00397 } else {
00398 return ELIMIT;
00399 }
00400 }
00401 } while (socket_cores_find(local_sockets,
00402 ((positive ? 1 : -1) * socket_id)));
00403
00404
00405 return socket_id;
00406 }
00407
00420 int
00421 socket_create(socket_cores_t *local_sockets, int app_phone,
00422 void *specific_data, int *socket_id)
00423 {
00424 socket_core_t *socket;
00425 int positive;
00426 int rc;
00427
00428 if (!socket_id)
00429 return EINVAL;
00430
00431
00432 if (*socket_id <= 0) {
00433 positive = (*socket_id == 0);
00434 *socket_id = socket_generate_new_id(local_sockets, positive);
00435 if (*socket_id <= 0)
00436 return *socket_id;
00437 if (!positive)
00438 *socket_id *= -1;
00439 } else if(socket_cores_find(local_sockets, *socket_id)) {
00440 return EEXIST;
00441 }
00442
00443 socket = (socket_core_t *) malloc(sizeof(*socket));
00444 if (!socket)
00445 return ENOMEM;
00446
00447
00448 socket->phone = app_phone;
00449 socket->port = -1;
00450 socket->key = NULL;
00451 socket->key_length = 0;
00452 socket->specific_data = specific_data;
00453 rc = dyn_fifo_initialize(&socket->received, SOCKET_INITIAL_RECEIVED_SIZE);
00454 if (rc != EOK) {
00455 free(socket);
00456 return rc;
00457 }
00458
00459 rc = dyn_fifo_initialize(&socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE);
00460 if (rc != EOK) {
00461 dyn_fifo_destroy(&socket->received);
00462 free(socket);
00463 return rc;
00464 }
00465 socket->socket_id = *socket_id;
00466 rc = socket_cores_add(local_sockets, socket->socket_id, socket);
00467 if (rc < 0) {
00468 dyn_fifo_destroy(&socket->received);
00469 dyn_fifo_destroy(&socket->accepted);
00470 free(socket);
00471 return rc;
00472 }
00473
00474 return EOK;
00475 }
00476
00491 int
00492 socket_destroy(int packet_phone, int socket_id, socket_cores_t *local_sockets,
00493 socket_ports_t *global_sockets,
00494 void (*socket_release)(socket_core_t *socket))
00495 {
00496 socket_core_t *socket;
00497 int accepted_id;
00498
00499
00500 socket = socket_cores_find(local_sockets, socket_id);
00501 if (!socket)
00502 return ENOTSOCK;
00503
00504
00505 while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
00506 socket_destroy(packet_phone, accepted_id, local_sockets,
00507 global_sockets, socket_release);
00508
00509 socket_destroy_core(packet_phone, socket, local_sockets, global_sockets,
00510 socket_release);
00511
00512 return EOK;
00513 }
00514
00528 int socket_reply_packets(packet_t *packet, size_t *length)
00529 {
00530 packet_t *next_packet;
00531 size_t fragments;
00532 size_t *lengths;
00533 size_t index;
00534 int rc;
00535
00536 if (!length)
00537 return EBADMEM;
00538
00539 next_packet = pq_next(packet);
00540 if (!next_packet) {
00541
00542 rc = data_reply(packet_get_data(packet),
00543 packet_get_data_length(packet));
00544 if (rc != EOK)
00545 return rc;
00546
00547 *length = packet_get_data_length(packet);
00548 } else {
00549
00550 fragments = 1;
00551 next_packet = pq_next(packet);
00552 while ((next_packet = pq_next(next_packet)))
00553 ++fragments;
00554
00555
00556 lengths = (size_t *) malloc(sizeof(size_t) * fragments +
00557 sizeof(size_t));
00558 if (!lengths)
00559 return ENOMEM;
00560
00561 lengths[0] = packet_get_data_length(packet);
00562 lengths[fragments] = lengths[0];
00563 next_packet = pq_next(packet);
00564
00565 for (index = 1; index < fragments; ++index) {
00566 lengths[index] = packet_get_data_length(next_packet);
00567 lengths[fragments] += lengths[index];
00568 next_packet = pq_next(packet);
00569 }
00570
00571
00572 rc = data_reply(lengths, sizeof(int) * (fragments + 1));
00573 if (rc != EOK) {
00574 free(lengths);
00575 return rc;
00576 }
00577 next_packet = packet;
00578
00579
00580 for (index = 0; index < fragments; ++index) {
00581 rc = data_reply(packet_get_data(next_packet),
00582 lengths[index]);
00583 if (rc != EOK) {
00584 free(lengths);
00585 return rc;
00586 }
00587 next_packet = pq_next(next_packet);
00588 }
00589
00590
00591 *length = lengths[fragments];
00592 free(lengths);
00593 }
00594
00595 return EOK;
00596 }
00597
00607 socket_core_t *
00608 socket_port_find(socket_ports_t *global_sockets, int port, const uint8_t *key,
00609 size_t key_length)
00610 {
00611 socket_port_t *socket_port;
00612 socket_core_t **socket_ref;
00613
00614 socket_port = socket_ports_find(global_sockets, port);
00615 if (socket_port && (socket_port->count > 0)) {
00616 socket_ref = socket_port_map_find(&socket_port->map, key,
00617 key_length);
00618 if (socket_ref)
00619 return *socket_ref;
00620 }
00621
00622 return NULL;
00623 }
00624
00633 void
00634 socket_port_release(socket_ports_t *global_sockets, socket_core_t *socket)
00635 {
00636 socket_port_t *socket_port;
00637 socket_core_t **socket_ref;
00638
00639 if (!socket->port)
00640 return;
00641
00642
00643 socket_port = socket_ports_find(global_sockets, socket->port);
00644 if (socket_port) {
00645
00646 socket_ref = socket_port_map_find(&socket_port->map,
00647 socket->key, socket->key_length);
00648
00649 if (socket_ref) {
00650 --socket_port->count;
00651
00652
00653 if (socket_port->count <= 0) {
00654
00655 socket_port_map_destroy(&socket_port->map, free);
00656
00657 socket_ports_exclude(global_sockets,
00658 socket->port, free);
00659 } else {
00660
00661 socket_port_map_exclude(&socket_port->map,
00662 socket->key, socket->key_length, free);
00663 }
00664 }
00665 }
00666
00667 socket->port = 0;
00668 socket->key = NULL;
00669 socket->key_length = 0;
00670 }
00671
00684 int
00685 socket_port_add(socket_ports_t *global_sockets, int port,
00686 socket_core_t *socket, const uint8_t *key, size_t key_length)
00687 {
00688 socket_port_t *socket_port;
00689 int rc;
00690
00691
00692 socket_port = socket_ports_find(global_sockets, port);
00693 if (!socket_port)
00694 return ENOENT;
00695
00696
00697 rc = socket_port_add_core(socket_port, socket, key, key_length);
00698 if (rc != EOK)
00699 return rc;
00700
00701 socket->port = port;
00702 return EOK;
00703 }
00704