Changeset 357b5f5 in mainline for uspace/srv/net/tl/tcp/tcp.c
- Timestamp:
- 2011-01-23T20:09:13Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- fdb9982c
- Parents:
- cead2aa (diff), 7e36c8d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/tcp/tcp.c
rcead2aa r357b5f5 36 36 */ 37 37 38 #include "tcp.h"39 #include "tcp_header.h"40 #include "tcp_module.h"41 42 38 #include <assert.h> 43 39 #include <async.h> … … 68 64 #include <ip_interface.h> 69 65 #include <icmp_client.h> 70 #include <icmp_ interface.h>66 #include <icmp_remote.h> 71 67 #include <net_interface.h> 72 68 #include <socket_core.h> 73 69 #include <tl_common.h> 74 #include <tl_local.h> 75 #include <tl_interface.h> 70 #include <tl_remote.h> 71 #include <tl_skel.h> 72 73 #include "tcp.h" 74 #include "tcp_header.h" 76 75 77 76 /** TCP module name. */ 78 #define NAME "TCP protocol"77 #define NAME "tcp" 79 78 80 79 /** The TCP window default value. */ … … 154 153 155 154 /** Port map key. */ 156 char*key;155 uint8_t *key; 157 156 158 157 /** Port map key length. */ … … 205 204 static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *, 206 205 packet_t *, int, size_t); 206 static void tcp_queue_received_end_of_data(socket_core_t *socket); 207 207 208 208 static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t); … … 219 219 /** TCP global data. */ 220 220 tcp_globals_t tcp_globals; 221 222 /** Initializes the TCP module.223 *224 * @param[in] client_connection The client connection processing function. The225 * module skeleton propagates its own one.226 * @return EOK on success.227 * @return ENOMEM if there is not enough memory left.228 */229 int tcp_initialize(async_client_conn_t client_connection)230 {231 int rc;232 233 assert(client_connection);234 235 fibril_rwlock_initialize(&tcp_globals.lock);236 fibril_rwlock_write_lock(&tcp_globals.lock);237 238 tcp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,239 ICMP_CONNECT_TIMEOUT);240 tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,241 SERVICE_TCP, client_connection);242 if (tcp_globals.ip_phone < 0) {243 fibril_rwlock_write_unlock(&tcp_globals.lock);244 return tcp_globals.ip_phone;245 }246 247 rc = socket_ports_initialize(&tcp_globals.sockets);248 if (rc != EOK)249 goto out;250 251 rc = packet_dimensions_initialize(&tcp_globals.dimensions);252 if (rc != EOK) {253 socket_ports_destroy(&tcp_globals.sockets);254 goto out;255 }256 257 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;258 259 out:260 fibril_rwlock_write_unlock(&tcp_globals.lock);261 return rc;262 }263 221 264 222 int tcp_received_msg(device_id_t device_id, packet_t *packet, … … 357 315 /* Find the destination socket */ 358 316 socket = socket_port_find(&tcp_globals.sockets, 359 ntohs(header->destination_port), ( const char*) src, addrlen);317 ntohs(header->destination_port), (uint8_t *) src, addrlen); 360 318 if (!socket) { 361 319 /* Find the listening destination socket */ 362 320 socket = socket_port_find(&tcp_globals.sockets, 363 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING,364 0);321 ntohs(header->destination_port), 322 (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 365 323 } 366 324 … … 453 411 454 412 has_error_service: 455 fibril_rwlock_ read_unlock(&tcp_globals.lock);413 fibril_rwlock_write_unlock(&tcp_globals.lock); 456 414 457 415 /* TODO error reporting/handling */ … … 504 462 size_t offset; 505 463 uint32_t new_sequence_number; 464 bool forced_ack; 506 465 int rc; 507 466 … … 512 471 assert(packet); 513 472 473 forced_ack = false; 474 514 475 new_sequence_number = ntohl(header->sequence_number); 515 476 old_incoming = socket_data->next_incoming; 516 477 517 if (header->finalize) 518 socket_data->fin_incoming = new_sequence_number; 478 if (header->finalize) { 479 socket_data->fin_incoming = new_sequence_number + 480 total_length - TCP_HEADER_LENGTH(header); 481 } 519 482 520 483 /* Trim begining if containing expected data */ … … 760 723 /* Release duplicite or restricted */ 761 724 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet)); 762 } 763 764 /* Change state according to the acknowledging incoming fin */ 765 if (IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming, 766 socket_data->next_incoming)) { 725 forced_ack = true; 726 } 727 728 /* If next in sequence is an incoming FIN */ 729 if (socket_data->next_incoming == socket_data->fin_incoming) { 730 /* Advance sequence number */ 731 socket_data->next_incoming += 1; 732 733 /* Handle FIN */ 767 734 switch (socket_data->state) { 768 735 case TCP_SOCKET_FIN_WAIT_1: … … 771 738 socket_data->state = TCP_SOCKET_CLOSING; 772 739 break; 773 /*case TCP_ESTABLISHED:*/ 740 case TCP_SOCKET_ESTABLISHED: 741 /* Queue end-of-data marker on the socket. */ 742 tcp_queue_received_end_of_data(socket); 743 socket_data->state = TCP_SOCKET_CLOSE_WAIT; 744 break; 774 745 default: 775 746 socket_data->state = TCP_SOCKET_CLOSE_WAIT; … … 779 750 780 751 packet = tcp_get_packets_to_send(socket, socket_data); 781 if (!packet ) {752 if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) { 782 753 /* Create the notification packet */ 783 754 rc = tcp_create_notification_packet(&packet, socket, … … 829 800 /* Notify the destination socket */ 830 801 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 831 ( ipcarg_t) socket->socket_id,802 (sysarg_t) socket->socket_id, 832 803 ((packet_dimension->content < socket_data->data_fragment_size) ? 833 804 packet_dimension->content : socket_data->data_fragment_size), 0, 0, 834 ( ipcarg_t) fragments);805 (sysarg_t) fragments); 835 806 836 807 return EOK; 808 } 809 810 /** Queue end-of-data marker on the socket. 811 * 812 * Next element in the sequence space is FIN. Queue end-of-data marker 813 * on the socket. 814 * 815 * @param socket Socket 816 */ 817 static void tcp_queue_received_end_of_data(socket_core_t *socket) 818 { 819 assert(socket != NULL); 820 821 /* Notify the destination socket */ 822 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 823 (sysarg_t) socket->socket_id, 824 0, 0, 0, 825 (sysarg_t) 0 /* 0 fragments == no more data */); 837 826 } 838 827 … … 966 955 /* Find the destination socket */ 967 956 listening_socket = socket_port_find(&tcp_globals.sockets, 968 listening_port, SOCKET_MAP_KEY_LISTENING, 0);957 listening_port, (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 969 958 if (!listening_socket || 970 959 (listening_socket->socket_id != listening_socket_id)) { … … 990 979 991 980 rc = socket_port_add(&tcp_globals.sockets, listening_port, socket, 992 ( const char*) socket_data->addr, socket_data->addrlen);981 (uint8_t *) socket_data->addr, socket_data->addrlen); 993 982 assert(socket == socket_port_find(&tcp_globals.sockets, listening_port, 994 ( const char*) socket_data->addr, socket_data->addrlen));983 (uint8_t *) socket_data->addr, socket_data->addrlen)); 995 984 996 985 // rc = socket_bind_free_port(&tcp_globals.sockets, socket, … … 1090 1079 /* Notify the destination socket */ 1091 1080 async_msg_5(socket->phone, NET_SOCKET_ACCEPTED, 1092 ( ipcarg_t) listening_socket->socket_id,1081 (sysarg_t) listening_socket->socket_id, 1093 1082 socket_data->data_fragment_size, TCP_HEADER_SIZE, 1094 0, ( ipcarg_t) socket->socket_id);1083 0, (sysarg_t) socket->socket_id); 1095 1084 1096 1085 fibril_rwlock_write_unlock(socket_data->local_lock); … … 1215 1204 } 1216 1205 1206 /** Per-connection initialization 1207 * 1208 */ 1209 void tl_connection(void) 1210 { 1211 } 1212 1217 1213 /** Processes the TCP message. 1218 1214 * … … 1228 1224 * @see IS_NET_TCP_MESSAGE() 1229 1225 */ 1230 int 1231 tcp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 1232 ipc_call_t *answer, int *answer_count) 1233 { 1234 packet_t *packet; 1235 int rc; 1236 1226 int tl_message(ipc_callid_t callid, ipc_call_t *call, 1227 ipc_call_t *answer, size_t *answer_count) 1228 { 1237 1229 assert(call); 1238 1230 assert(answer); … … 1240 1232 1241 1233 *answer_count = 0; 1242 switch (IPC_GET_METHOD(*call)) { 1243 case NET_TL_RECEIVED: 1244 // fibril_rwlock_read_lock(&tcp_globals.lock); 1245 rc = packet_translate_remote(tcp_globals.net_phone, &packet, 1246 IPC_GET_PACKET(call)); 1247 if (rc != EOK) { 1248 // fibril_rwlock_read_unlock(&tcp_globals.lock); 1249 return rc; 1250 } 1251 rc = tcp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_TCP, 1252 IPC_GET_ERROR(call)); 1253 // fibril_rwlock_read_unlock(&tcp_globals.lock); 1254 return rc; 1234 switch (IPC_GET_IMETHOD(*call)) { 1255 1235 case IPC_M_CONNECT_TO_ME: 1256 1236 return tcp_process_client_messages(callid, *call); … … 1291 1271 bool keep_on_going = true; 1292 1272 socket_cores_t local_sockets; 1293 int app_phone = IPC_GET_PHONE( &call);1273 int app_phone = IPC_GET_PHONE(call); 1294 1274 struct sockaddr *addr; 1295 1275 int socket_id; … … 1298 1278 fibril_rwlock_t lock; 1299 1279 ipc_call_t answer; 1300 int answer_count;1280 size_t answer_count; 1301 1281 tcp_socket_data_t *socket_data; 1302 1282 socket_core_t *socket; … … 1323 1303 1324 1304 /* Process the call */ 1325 switch (IPC_GET_ METHOD(call)) {1305 switch (IPC_GET_IMETHOD(call)) { 1326 1306 case IPC_M_PHONE_HUNGUP: 1327 1307 keep_on_going = false; … … 1365 1345 1366 1346 case NET_SOCKET_BIND: 1367 res = data_receive((void **) &addr, &addrlen); 1347 res = async_data_write_accept((void **) &addr, false, 1348 0, 0, 0, &addrlen); 1368 1349 if (res != EOK) 1369 1350 break; … … 1402 1383 1403 1384 case NET_SOCKET_CONNECT: 1404 res = data_receive((void **) &addr, &addrlen); 1385 res = async_data_write_accept((void **) &addr, false, 1386 0, 0, 0, &addrlen); 1405 1387 if (res != EOK) 1406 1388 break; … … 1453 1435 1454 1436 case NET_SOCKET_SENDTO: 1455 res = data_receive((void **) &addr, &addrlen); 1437 res = async_data_write_accept((void **) &addr, false, 1438 0, 0, 0, &addrlen); 1456 1439 if (res != EOK) 1457 1440 break; … … 1800 1783 fibril_rwlock_write_unlock(socket_data->local_lock); 1801 1784 1785 socket_data->state = TCP_SOCKET_SYN_SENT; 1786 1802 1787 /* Send the packet */ 1803 1788 printf("connecting %d\n", packet_get_id(packet)); … … 2072 2057 2073 2058 /* Copy the key */ 2074 operation_timeout->key = (( char*) operation_timeout) +2059 operation_timeout->key = ((uint8_t *) operation_timeout) + 2075 2060 sizeof(*operation_timeout); 2076 2061 operation_timeout->key_length = socket->key_length; … … 2082 2067 if (!fibril) { 2083 2068 free(operation_timeout); 2084 return EPARTY; /* FIXME: use another EC */ 2085 } 2069 return ENOMEM; 2070 } 2071 2086 2072 // fibril_mutex_lock(&socket_data->operation.mutex); 2087 2073 /* Start the timeout fibril */ … … 2206 2192 2207 2193 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 2208 rc = tcp_queue_packet(socket, socket_data, packet, 0);2194 rc = tcp_queue_packet(socket, socket_data, packet, total_length); 2209 2195 if (rc != EOK) 2210 2196 return rc; … … 2448 2434 } 2449 2435 2450 /** Default thread for new connections.2436 /** Process IPC messages from the IP module 2451 2437 * 2452 * @param[in] iid The initial message identifier.2453 * @param[in ] icall The initial message call structure.2438 * @param[in] iid Message identifier. 2439 * @param[in,out] icall Message parameters. 2454 2440 * 2455 2441 */ 2456 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall) 2457 { 2458 /* 2459 * Accept the connection 2460 * - Answer the first IPC_M_CONNECT_ME_TO call. 2461 */ 2462 ipc_answer_0(iid, EOK); 2463 2442 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall) 2443 { 2444 packet_t *packet; 2445 int rc; 2446 2464 2447 while (true) { 2465 ipc_call_t answer; 2466 int answer_count; 2467 2468 /* Clear the answer structure */ 2469 refresh_answer(&answer, &answer_count); 2470 2471 /* Fetch the next message */ 2472 ipc_call_t call; 2473 ipc_callid_t callid = async_get_call(&call); 2474 2475 /* Process the message */ 2476 int res = tl_module_message_standalone(callid, &call, &answer, 2477 &answer_count); 2478 2479 /* 2480 * End if told to either by the message or the processing 2481 * result. 2482 */ 2483 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 2484 (res == EHANGUP)) 2485 return; 2486 2487 /* 2488 * Answer the message 2489 */ 2490 answer_call(callid, res, &answer, answer_count); 2491 } 2492 } 2493 2494 /** Starts the module. 2448 switch (IPC_GET_IMETHOD(*icall)) { 2449 case NET_TL_RECEIVED: 2450 rc = packet_translate_remote(tcp_globals.net_phone, &packet, 2451 IPC_GET_PACKET(*icall)); 2452 if (rc == EOK) 2453 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 2454 SERVICE_TCP, IPC_GET_ERROR(*icall)); 2455 2456 ipc_answer_0(iid, (sysarg_t) rc); 2457 break; 2458 default: 2459 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 2460 } 2461 2462 iid = async_get_call(icall); 2463 } 2464 } 2465 2466 /** Initialize the TCP module. 2495 2467 * 2496 * @return EOK on success. 2497 * @return Other error codes as defined for each specific module 2498 * start function. 2468 * @param[in] net_phone Network module phone. 2469 * 2470 * @return EOK on success. 2471 * @return ENOMEM if there is not enough memory left. 2472 * 2499 2473 */ 2500 int 2501 main(int argc, char *argv[]) 2502 { 2503 int rc; 2504 2505 rc = tl_module_start_standalone(tl_client_connection); 2474 int tl_initialize(int net_phone) 2475 { 2476 fibril_rwlock_initialize(&tcp_globals.lock); 2477 fibril_rwlock_write_lock(&tcp_globals.lock); 2478 2479 tcp_globals.net_phone = net_phone; 2480 2481 tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT); 2482 tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP, 2483 SERVICE_TCP, tcp_receiver); 2484 if (tcp_globals.ip_phone < 0) { 2485 fibril_rwlock_write_unlock(&tcp_globals.lock); 2486 return tcp_globals.ip_phone; 2487 } 2488 2489 int rc = socket_ports_initialize(&tcp_globals.sockets); 2490 if (rc != EOK) 2491 goto out; 2492 2493 rc = packet_dimensions_initialize(&tcp_globals.dimensions); 2494 if (rc != EOK) { 2495 socket_ports_destroy(&tcp_globals.sockets); 2496 goto out; 2497 } 2498 2499 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1; 2500 2501 out: 2502 fibril_rwlock_write_unlock(&tcp_globals.lock); 2506 2503 return rc; 2504 } 2505 2506 int main(int argc, char *argv[]) 2507 { 2508 return tl_module_start(SERVICE_TCP); 2507 2509 } 2508 2510
Note:
See TracChangeset
for help on using the changeset viewer.