Changeset 3f0a7971 in mainline for uspace/srv/net/tl/tcp/tcp.c
- Timestamp:
- 2010-11-18T22:34:23Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 63b4f90
- Parents:
- c7137738 (diff), 45f04f8 (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
rc7137738 r3f0a7971 44 44 #include <fibril_synch.h> 45 45 #include <malloc.h> 46 / /TODO remove stdio46 /* TODO remove stdio */ 47 47 #include <stdio.h> 48 48 #include <errno.h> … … 267 267 } 268 268 269 int 270 tcp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 271 services_t error) 269 int tcp_received_msg(device_id_t device_id, packet_t packet, 270 services_t receiver, services_t error) 272 271 { 273 272 int rc; … … 309 308 break; 310 309 case SERVICE_ICMP: 311 / / process error310 /* Process error */ 312 311 result = icmp_client_process_packet(packet, &type, &code, NULL, 313 312 NULL); … … 324 323 } 325 324 326 / / TODO process received ipopts?325 /* TODO process received ipopts? */ 327 326 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 328 327 if (result < 0) … … 338 337 return tcp_release_and_return(packet, NO_DATA); 339 338 340 / / trim all but TCP header339 /* Trim all but TCP header */ 341 340 rc = packet_trim(packet, offset, 0); 342 341 if (rc != EOK) 343 342 return tcp_release_and_return(packet, rc); 344 343 345 / / get tcp header344 /* Get tcp header */ 346 345 header = (tcp_header_ref) packet_get_data(packet); 347 346 if (!header) … … 361 360 return tcp_release_and_return(packet, rc); 362 361 363 / / find the destination socket362 /* Find the destination socket */ 364 363 socket = socket_port_find(&tcp_globals.sockets, 365 364 ntohs(header->destination_port), (const char *) src, addrlen); 366 365 if (!socket) { 367 / / find the listening destination socket366 /* Find the listening destination socket */ 368 367 socket = socket_port_find(&tcp_globals.sockets, 369 368 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 370 369 0); 371 370 } 371 372 372 if (!socket) { 373 373 if (tl_prepare_icmp_packet(tcp_globals.net_phone, … … 383 383 assert(socket_data); 384 384 385 / / some data received, clear the timeout counter385 /* Some data received, clear the timeout counter */ 386 386 socket_data->timeout_count = 0; 387 387 388 / / count the received packet fragments388 /* Count the received packet fragments */ 389 389 next_packet = packet; 390 390 fragments = 0; … … 399 399 total_length += length; 400 400 401 / / add partial checksum if set401 /* Add partial checksum if set */ 402 402 if (!error) { 403 403 checksum = compute_checksum(checksum, … … 447 447 tcp_globals.icmp_phone, packet, error); 448 448 if (rc == EOK) { 449 / / checksum error ICMP449 /* Checksum error ICMP */ 450 450 icmp_parameter_problem_msg(tcp_globals.icmp_phone, 451 451 ICMP_PARAM_POINTER, … … 460 460 fibril_rwlock_read_unlock(&tcp_globals.lock); 461 461 462 / / TODO error reporting/handling462 /* TODO error reporting/handling */ 463 463 switch (socket_data->state) { 464 464 case TCP_SOCKET_LISTEN: … … 474 474 break; 475 475 case TCP_SOCKET_FIN_WAIT_1: 476 / / ack changing the state to FIN_WAIT_2 gets processed later476 /* ack changing the state to FIN_WAIT_2 gets processed later */ 477 477 case TCP_SOCKET_FIN_WAIT_2: 478 / / fin changing state to LAST_ACK gets processed later478 /* fin changing state to LAST_ACK gets processed later */ 479 479 case TCP_SOCKET_LAST_ACK: 480 / / ack releasing the socket get processed later480 /* ack releasing the socket get processed later */ 481 481 case TCP_SOCKET_CLOSING: 482 / / ack releasing the socket gets processed later482 /* ack releasing the socket gets processed later */ 483 483 case TCP_SOCKET_ESTABLISHED: 484 484 rc = tcp_process_established(socket, socket_data, header, … … 497 497 } 498 498 499 int 500 tcp_process_established(socket_core_ref socket, tcp_socket_data_ref socket_data,501 tcp_header_ref header, packet_t packet, int fragments,size_t total_length)499 int tcp_process_established(socket_core_ref socket, tcp_socket_data_ref 500 socket_data, tcp_header_ref header, packet_t packet, int fragments, 501 size_t total_length) 502 502 { 503 503 packet_t next_packet; … … 523 523 socket_data->fin_incoming = new_sequence_number; 524 524 525 / / trim begining if containing expected data525 /* Trim begining if containing expected data */ 526 526 if (IS_IN_INTERVAL_OVERFLOW(new_sequence_number, 527 527 socket_data->next_incoming, new_sequence_number + total_length)) { 528 528 529 / / get the acknowledged offset529 /* Get the acknowledged offset */ 530 530 if (socket_data->next_incoming < new_sequence_number) { 531 531 offset = new_sequence_number - … … 539 539 total_length -= offset; 540 540 length = packet_get_data_length(packet); 541 // trim the acknowledged data 541 542 /* Trim the acknowledged data */ 542 543 while (length <= offset) { 543 / / release the acknowledged packets544 /* Release the acknowledged packets */ 544 545 next_packet = pq_next(packet); 545 546 pq_release_remote(tcp_globals.net_phone, … … 559 560 } 560 561 561 / / release if overflowing the window562 /* Release if overflowing the window */ 562 563 /* 563 564 if (IS_IN_INTERVAL_OVERFLOW(socket_data->next_incoming + … … 609 610 } 610 611 */ 611 / / the expected one arrived?612 /* The expected one arrived? */ 612 613 if (new_sequence_number == socket_data->next_incoming) { 613 614 printf("expected\n"); 614 / / process acknowledgement615 /* Process acknowledgement */ 615 616 tcp_process_acknowledgement(socket, socket_data, header); 616 617 617 / / remove the header618 /* Remove the header */ 618 619 total_length -= TCP_HEADER_LENGTH(header); 619 620 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0); … … 635 636 rc = pq_get_order(socket_data->incoming, &order, NULL); 636 637 if (rc != EOK) { 637 / / remove the corrupted packet638 /* Remove the corrupted packet */ 638 639 next_packet = pq_detach(packet); 639 640 if (packet == socket_data->incoming) … … 648 649 if (IS_IN_INTERVAL_OVERFLOW(sequence_number, 649 650 old_incoming, socket_data->next_incoming)) { 650 / / move to the next651 /* Move to the next */ 651 652 packet = pq_next(packet); 652 / / coninual data?653 /* Coninual data? */ 653 654 } else if (IS_IN_INTERVAL_OVERFLOW(old_incoming, 654 655 sequence_number, socket_data->next_incoming)) { 655 / / detach the packet656 /* Detach the packet */ 656 657 next_packet = pq_detach(packet); 657 658 if (packet == socket_data->incoming) 658 659 socket_data->incoming = next_packet; 659 / / get data length660 /* Get data length */ 660 661 length = packet_get_data_length(packet); 661 662 new_sequence_number = sequence_number + length; 662 663 if (length <= 0) { 663 / / remove the empty packet664 /* Remove the empty packet */ 664 665 pq_release_remote(tcp_globals.net_phone, 665 666 packet_get_id(packet)); … … 667 668 continue; 668 669 } 669 / / exactly following670 /* Exactly following */ 670 671 if (sequence_number == 671 672 socket_data->next_incoming) { 672 / / queue received data673 /* Queue received data */ 673 674 rc = tcp_queue_received_packet(socket, 674 675 socket_data, packet, 1, … … 680 681 packet = next_packet; 681 682 continue; 682 / / at least partly following data?683 /* At least partly following data? */ 683 684 } 684 685 if (IS_IN_INTERVAL_OVERFLOW(sequence_number, … … 695 696 rc = packet_trim(packet,length, 0); 696 697 if (rc == EOK) { 697 / / queue received data698 /* Queue received data */ 698 699 rc = tcp_queue_received_packet( 699 700 socket, socket_data, packet, … … 708 709 } 709 710 } 710 / / remove the duplicit or corrupted packet711 /* Remove the duplicit or corrupted packet */ 711 712 pq_release_remote(tcp_globals.net_phone, 712 713 packet_get_id(packet)); … … 721 722 socket_data->next_incoming + socket_data->window)) { 722 723 printf("in window\n"); 723 / / process acknowledgement724 /* Process acknowledgement */ 724 725 tcp_process_acknowledgement(socket, socket_data, header); 725 726 726 / / remove the header727 /* Remove the header */ 727 728 total_length -= TCP_HEADER_LENGTH(header); 728 729 rc = packet_trim(packet, TCP_HEADER_LENGTH(header), 0); … … 735 736 length); 736 737 if (rc != EOK) { 737 / / remove the corrupted packets738 /* Remove the corrupted packets */ 738 739 pq_release_remote(tcp_globals.net_phone, 739 740 packet_get_id(packet)); … … 762 763 } else { 763 764 printf("unexpected\n"); 764 / / release duplicite or restricted765 /* Release duplicite or restricted */ 765 766 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet)); 766 767 } 767 768 768 / / change state according to the acknowledging incoming fin769 /* Change state according to the acknowledging incoming fin */ 769 770 if (IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming, 770 771 socket_data->next_incoming)) { … … 775 776 socket_data->state = TCP_SOCKET_CLOSING; 776 777 break; 777 //case TCP_ESTABLISHED:778 /*case TCP_ESTABLISHED:*/ 778 779 default: 779 780 socket_data->state = TCP_SOCKET_CLOSE_WAIT; … … 784 785 packet = tcp_get_packets_to_send(socket, socket_data); 785 786 if (!packet) { 786 / / create the notification packet787 /* Create the notification packet */ 787 788 rc = tcp_create_notification_packet(&packet, socket, 788 789 socket_data, 0, 0); … … 798 799 fibril_rwlock_write_unlock(socket_data->local_lock); 799 800 800 / / send the packet801 /* Send the packet */ 801 802 tcp_send_packets(socket_data->device_id, packet); 802 803 … … 804 805 } 805 806 806 int 807 tcp_queue_received_packet(socket_core_ref socket, 807 int tcp_queue_received_packet(socket_core_ref socket, 808 808 tcp_socket_data_ref socket_data, packet_t packet, int fragments, 809 809 size_t total_length) … … 819 819 assert(socket_data->window > total_length); 820 820 821 / / queue the received packet821 /* Queue the received packet */ 822 822 rc = dyn_fifo_push(&socket->received, packet_get_id(packet), 823 823 SOCKET_MAX_RECEIVED_SIZE); … … 829 829 return tcp_release_and_return(packet, rc); 830 830 831 / / decrease the window size831 /* Decrease the window size */ 832 832 socket_data->window -= total_length; 833 833 834 / / notify the destination socket834 /* Notify the destination socket */ 835 835 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 836 836 (ipcarg_t) socket->socket_id, … … 842 842 } 843 843 844 int 845 tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref socket_data, 846 tcp_header_ref header, packet_t packet) 844 int tcp_process_syn_sent(socket_core_ref socket, tcp_socket_data_ref 845 socket_data, tcp_header_ref header, packet_t packet) 847 846 { 848 847 packet_t next_packet; … … 858 857 return tcp_release_and_return(packet, EINVAL); 859 858 860 / / process acknowledgement859 /* Process acknowledgement */ 861 860 tcp_process_acknowledgement(socket, socket_data, header); 862 861 863 862 socket_data->next_incoming = ntohl(header->sequence_number) + 1; 864 // release additional packets 863 864 /* Release additional packets */ 865 865 next_packet = pq_detach(packet); 866 866 if (next_packet) { … … 868 868 packet_get_id(next_packet)); 869 869 } 870 // trim if longer than the header 870 871 /* Trim if longer than the header */ 871 872 if (packet_get_data_length(packet) > sizeof(*header)) { 872 873 rc = packet_trim(packet, 0, … … 875 876 return tcp_release_and_return(packet, rc); 876 877 } 878 877 879 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 878 880 fibril_mutex_lock(&socket_data->operation.mutex); 879 881 socket_data->operation.result = tcp_queue_packet(socket, socket_data, 880 882 packet, 1); 883 881 884 if (socket_data->operation.result == EOK) { 882 885 socket_data->state = TCP_SOCKET_ESTABLISHED; … … 884 887 if (packet) { 885 888 fibril_rwlock_write_unlock( socket_data->local_lock); 886 / / send the packet889 /* Send the packet */ 887 890 tcp_send_packets(socket_data->device_id, packet); 888 / / signal the result891 /* Signal the result */ 889 892 fibril_condvar_signal( &socket_data->operation.condvar); 890 893 fibril_mutex_unlock( &socket_data->operation.mutex); … … 892 895 } 893 896 } 897 894 898 fibril_mutex_unlock(&socket_data->operation.mutex); 895 899 return tcp_release_and_return(packet, EINVAL); 896 900 } 897 901 898 int 899 tcp_process_listen(socket_core_ref listening_socket, 902 int tcp_process_listen(socket_core_ref listening_socket, 900 903 tcp_socket_data_ref listening_socket_data, tcp_header_ref header, 901 904 packet_t packet, struct sockaddr *src, struct sockaddr *dest, … … 936 939 return tcp_release_and_return(packet, ENOMEM); 937 940 } 941 938 942 memcpy(socket_data->addr, src, socket_data->addrlen); 939 943 socket_data->dest_port = ntohs(header->source_port); … … 946 950 } 947 951 948 / / create a socket952 /* Create a socket */ 949 953 socket_id = -1; 950 954 rc = socket_create(socket_data->local_sockets, listening_socket->phone, … … 965 969 fibril_rwlock_write_lock(&tcp_globals.lock); 966 970 967 / / find the destination socket971 /* Find the destination socket */ 968 972 listening_socket = socket_port_find(&tcp_globals.sockets, 969 973 listening_port, SOCKET_MAP_KEY_LISTENING, 0); … … 971 975 (listening_socket->socket_id != listening_socket_id)) { 972 976 fibril_rwlock_write_unlock(&tcp_globals.lock); 973 / / a shadow may remain until app hangs up977 /* A shadow may remain until app hangs up */ 974 978 return tcp_release_and_return(packet, EOK /*ENOTSOCK*/); 975 979 } … … 983 987 socket_id); 984 988 if (!socket) { 985 / / where is the socket?!?989 /* Where is the socket?!? */ 986 990 fibril_rwlock_write_unlock(&tcp_globals.lock); 987 991 return ENOTSOCK; … … 1010 1014 socket_data->next_incoming = ntohl(header->sequence_number) + 1; 1011 1015 1012 / / release additional packets1016 /* Release additional packets */ 1013 1017 next_packet = pq_detach(packet); 1014 1018 if (next_packet) { … … 1017 1021 } 1018 1022 1019 / / trim if longer than the header1023 /* Trim if longer than the header */ 1020 1024 if (packet_get_data_length(packet) > sizeof(*header)) { 1021 1025 rc = packet_trim(packet, 0, … … 1050 1054 fibril_rwlock_write_unlock(socket_data->local_lock); 1051 1055 1052 / / send the packet1056 /* Send the packet */ 1053 1057 tcp_send_packets(socket_data->device_id, packet); 1054 1058 … … 1056 1060 } 1057 1061 1058 int 1059 tcp_process_syn_received(socket_core_ref socket, 1062 int tcp_process_syn_received(socket_core_ref socket, 1060 1063 tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet) 1061 1064 { … … 1073 1076 return tcp_release_and_return(packet, EINVAL); 1074 1077 1075 / / process acknowledgement1078 /* Process acknowledgement */ 1076 1079 tcp_process_acknowledgement(socket, socket_data, header); 1077 1080 … … 1086 1089 assert(listening_socket_data); 1087 1090 1088 / / queue the received packet1091 /* Queue the received packet */ 1089 1092 rc = dyn_fifo_push(&listening_socket->accepted, 1090 1093 (-1 * socket->socket_id), listening_socket_data->backlog); 1091 1094 if (rc == EOK) { 1092 / / notify the destination socket1095 /* Notify the destination socket */ 1093 1096 async_msg_5(socket->phone, NET_SOCKET_ACCEPTED, 1094 1097 (ipcarg_t) listening_socket->socket_id, … … 1100 1103 } 1101 1104 } 1102 / / send FIN1105 /* Send FIN */ 1103 1106 socket_data->state = TCP_SOCKET_FIN_WAIT_1; 1104 1107 1105 / / create the notification packet1108 /* Create the notification packet */ 1106 1109 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1); 1107 1110 if (rc != EOK) 1108 1111 return rc; 1109 1112 1110 / / send the packet1113 /* Send the packet */ 1111 1114 rc = tcp_queue_packet(socket, socket_data, packet, 1); 1112 1115 if (rc != EOK) 1113 1116 return rc; 1114 1117 1115 / / flush packets1118 /* Flush packets */ 1116 1119 packet = tcp_get_packets_to_send(socket, socket_data); 1117 1120 fibril_rwlock_write_unlock(socket_data->local_lock); 1118 1121 if (packet) { 1119 / / send the packet1122 /* Send the packet */ 1120 1123 tcp_send_packets(socket_data->device_id, packet); 1121 1124 } … … 1124 1127 } 1125 1128 1126 void 1127 tcp_process_acknowledgement(socket_core_ref socket, 1129 void tcp_process_acknowledgement(socket_core_ref socket, 1128 1130 tcp_socket_data_ref socket_data, tcp_header_ref header) 1129 1131 { … … 1144 1146 1145 1147 number = ntohl(header->acknowledgement_number); 1146 // if more data acknowledged 1148 1149 /* If more data acknowledged */ 1147 1150 if (number != socket_data->expected) { 1148 1151 old = socket_data->expected; … … 1155 1158 case TCP_SOCKET_LAST_ACK: 1156 1159 case TCP_SOCKET_CLOSING: 1157 // fin acknowledged - release the socket in 1158 // another fibril 1160 /* 1161 * FIN acknowledged - release the socket in 1162 * another fibril. 1163 */ 1159 1164 tcp_prepare_timeout(tcp_release_after_timeout, 1160 1165 socket, socket_data, 0, … … 1166 1171 } 1167 1172 } 1168 // update the treshold if higher than set 1173 1174 /* Update the treshold if higher than set */ 1169 1175 if (number + ntohs(header->window) > 1170 1176 socket_data->expected + socket_data->treshold) { … … 1172 1178 socket_data->expected; 1173 1179 } 1174 // set new expected sequence number 1180 1181 /* Set new expected sequence number */ 1175 1182 socket_data->expected = number; 1176 1183 socket_data->expected_count = 1; … … 1184 1191 socket_data->outgoing = next; 1185 1192 1186 / / add to acknowledged or release1193 /* Add to acknowledged or release */ 1187 1194 if (pq_add(&acknowledged, packet, 0, 0) != EOK) 1188 1195 pq_release_remote(tcp_globals.net_phone, … … 1192 1199 break; 1193 1200 } 1194 // release acknowledged 1201 1202 /* Release acknowledged */ 1195 1203 if (acknowledged) { 1196 1204 pq_release_remote(tcp_globals.net_phone, … … 1198 1206 } 1199 1207 return; 1200 // if the same as the previous time 1201 } 1208 /* If the same as the previous time */ 1209 } 1210 1202 1211 if (number == socket_data->expected) { 1203 / / increase the counter1212 /* Increase the counter */ 1204 1213 socket_data->expected_count++; 1205 1214 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) { 1206 1215 socket_data->expected_count = 1; 1207 / / TODO retransmit lock1216 /* TODO retransmit lock */ 1208 1217 //tcp_retransmit_packet(socket, socket_data, number); 1209 1218 } … … 1311 1320 while (keep_on_going) { 1312 1321 1313 / / answer the call1322 /* Answer the call */ 1314 1323 answer_call(callid, res, &answer, answer_count); 1315 / / refresh data1324 /* Refresh data */ 1316 1325 refresh_answer(&answer, &answer_count); 1317 / / get the next call1326 /* Get the next call */ 1318 1327 callid = async_get_call(&call); 1319 1328 1320 / / process the call1329 /* Process the call */ 1321 1330 switch (IPC_GET_METHOD(call)) { 1322 1331 case IPC_M_PHONE_HUNGUP: … … 1401 1410 if (res != EOK) 1402 1411 break; 1403 // the global lock may be released in the 1404 // tcp_connect_message() function 1412 /* 1413 * The global lock may be released in the 1414 * tcp_connect_message() function. 1415 */ 1405 1416 fibril_rwlock_write_lock(&tcp_globals.lock); 1406 1417 fibril_rwlock_write_lock(&lock); … … 1516 1527 } 1517 1528 1518 / / release the application phone1529 /* Release the application phone */ 1519 1530 ipc_hangup(app_phone); 1520 1531 1521 1532 printf("release\n"); 1522 / / release all local sockets1533 /* Release all local sockets */ 1523 1534 socket_cores_release(tcp_globals.net_phone, &local_sockets, 1524 1535 &tcp_globals.sockets, tcp_free_socket_data); … … 1536 1547 assert(timeout); 1537 1548 1538 / / sleep the given timeout1549 /* Sleep the given timeout */ 1539 1550 async_usleep(timeout->timeout); 1540 / / lock the globals1551 /* Lock the globals */ 1541 1552 if (timeout->globals_read_only) 1542 1553 fibril_rwlock_read_lock(&tcp_globals.lock); … … 1544 1555 fibril_rwlock_write_lock(&tcp_globals.lock); 1545 1556 1546 / / find the pending operation socket1557 /* Find the pending operation socket */ 1547 1558 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1548 1559 timeout->key, timeout->key_length); … … 1557 1568 fibril_rwlock_write_lock(socket_data->local_lock); 1558 1569 if (timeout->sequence_number) { 1559 / / increase the timeout counter;1570 /* Increase the timeout counter */ 1560 1571 socket_data->timeout_count++; 1561 1572 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) { 1562 / / TODO release as connection lost1573 /* TODO release as connection lost */ 1563 1574 //tcp_refresh_socket_data(socket_data); 1564 1575 fibril_rwlock_write_unlock(socket_data->local_lock); 1565 1576 } else { 1566 / / retransmit1577 /* Retransmit */ 1567 1578 // tcp_retransmit_packet(socket, 1568 1579 // socket_data, timeout->sequence_number); … … 1571 1582 } else { 1572 1583 fibril_mutex_lock(&socket_data->operation.mutex); 1573 // set the timeout operation result if state not 1574 // changed 1584 /* Set the timeout operation result if state not changed */ 1575 1585 if (socket_data->state == timeout->state) { 1576 1586 socket_data->operation.result = ETIMEOUT; 1577 // notify the main fibril 1587 1588 /* Notify the main fibril */ 1578 1589 fibril_condvar_signal(&socket_data->operation.condvar); 1579 // keep the global write lock 1590 1591 /* Keep the global write lock */ 1580 1592 keep_write_lock = true; 1581 1593 } else { 1582 // operation is ok, do nothing 1583 // unlocking from now on, so the unlocki 1584 // order does not matter... 1594 /* 1595 * Operation is ok, do nothing. 1596 * Unlocking from now on, so the unlocking 1597 * order does not matter. 1598 */ 1585 1599 fibril_rwlock_write_unlock(socket_data->local_lock); 1586 1600 } … … 1589 1603 1590 1604 out: 1591 / / unlock only if no socket1605 /* Unlock only if no socket */ 1592 1606 if (timeout->globals_read_only) 1593 1607 fibril_rwlock_read_unlock(&tcp_globals.lock); 1594 1608 else if (!keep_write_lock) 1595 / / release if not desired1609 /* Release if not desired */ 1596 1610 fibril_rwlock_write_unlock(&tcp_globals.lock); 1597 1611 1598 / / release the timeout structure1612 /* Release the timeout structure */ 1599 1613 free(timeout); 1600 1614 return EOK; … … 1610 1624 assert(timeout); 1611 1625 1612 / / sleep the given timeout1626 /* Sleep the given timeout */ 1613 1627 async_usleep(timeout->timeout); 1614 // lock the globals 1628 1629 /* Lock the globals */ 1615 1630 fibril_rwlock_write_lock(&tcp_globals.lock); 1616 // find the pending operation socket 1631 1632 /* Find the pending operation socket */ 1617 1633 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1618 1634 timeout->key, timeout->key_length); 1635 1619 1636 if (socket && (socket->socket_id == timeout->socket_id)) { 1620 1637 socket_data = (tcp_socket_data_ref) socket->specific_data; … … 1629 1646 } 1630 1647 } 1631 // unlock the globals 1648 1649 /* Unlock the globals */ 1632 1650 fibril_rwlock_write_unlock(&tcp_globals.lock); 1633 // release the timeout structure 1651 1652 /* Release the timeout structure */ 1634 1653 free(timeout); 1654 1635 1655 return EOK; 1636 1656 } 1637 1657 1638 void 1639 tcp_retransmit_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, 1640 size_t sequence_number) 1658 void tcp_retransmit_packet(socket_core_ref socket, tcp_socket_data_ref 1659 socket_data, size_t sequence_number) 1641 1660 { 1642 1661 packet_t packet; … … 1648 1667 assert(socket->specific_data == socket_data); 1649 1668 1650 / / sent packet?1669 /* Sent packet? */ 1651 1670 packet = pq_find(socket_data->outgoing, sequence_number); 1652 1671 printf("retransmit %d\n", packet_get_id(packet)); … … 1664 1683 } 1665 1684 1666 int 1667 tcp_listen_message(socket_cores_ref local_sockets, int socket_id,int backlog)1685 int tcp_listen_message(socket_cores_ref local_sockets, int socket_id, 1686 int backlog) 1668 1687 { 1669 1688 socket_core_ref socket; … … 1675 1694 return EINVAL; 1676 1695 1677 / / find the socket1696 /* Find the socket */ 1678 1697 socket = socket_cores_find(local_sockets, socket_id); 1679 1698 if (!socket) 1680 1699 return ENOTSOCK; 1681 1700 1682 / / get the socket specific data1701 /* Get the socket specific data */ 1683 1702 socket_data = (tcp_socket_data_ref) socket->specific_data; 1684 1703 assert(socket_data); 1685 // set the backlog 1704 1705 /* Set the backlog */ 1686 1706 socket_data->backlog = backlog; 1687 1707 … … 1689 1709 } 1690 1710 1691 int 1692 tcp_connect_message(socket_cores_ref local_sockets, int socket_id, 1711 int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, 1693 1712 struct sockaddr *addr, socklen_t addrlen) 1694 1713 { … … 1700 1719 assert(addrlen > 0); 1701 1720 1702 / / find the socket1721 /* Find the socket */ 1703 1722 socket = socket_cores_find(local_sockets, socket_id); 1704 1723 if (!socket) … … 1708 1727 if (rc != EOK) { 1709 1728 tcp_free_socket_data(socket); 1710 / / unbind if bound1729 /* Unbind if bound */ 1711 1730 if (socket->port > 0) { 1712 1731 socket_ports_exclude(&tcp_globals.sockets, … … 1718 1737 } 1719 1738 1720 int 1721 tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, 1739 int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, 1722 1740 struct sockaddr *addr, socklen_t addrlen) 1723 1741 { … … 1730 1748 assert(addrlen > 0); 1731 1749 1732 / / get the socket specific data1750 /* Get the socket specific data */ 1733 1751 socket_data = (tcp_socket_data_ref) socket->specific_data; 1734 1752 assert(socket_data); … … 1739 1757 return EINVAL; 1740 1758 1741 / / get the destination port1759 /* Get the destination port */ 1742 1760 rc = tl_get_address_port(addr, addrlen, &socket_data->dest_port); 1743 1761 if (rc != EOK) … … 1745 1763 1746 1764 if (socket->port <= 0) { 1747 / / try to find a free port1765 /* Try to find a free port */ 1748 1766 rc = socket_bind_free_port(&tcp_globals.sockets, socket, 1749 1767 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, … … 1751 1769 if (rc != EOK) 1752 1770 return rc; 1753 / / set the next port as the search starting port number1771 /* Set the next port as the search starting port number */ 1754 1772 tcp_globals.last_used_port = socket->port; 1755 1773 } … … 1761 1779 return rc; 1762 1780 1763 / / create the notification packet1781 /* Create the notification packet */ 1764 1782 rc = tcp_create_notification_packet(&packet, socket, socket_data, 1, 0); 1765 1783 if (rc != EOK) 1766 1784 return rc; 1767 1785 1768 / / unlock the globals and wait for an operation1786 /* Unlock the globals and wait for an operation */ 1769 1787 fibril_rwlock_write_unlock(&tcp_globals.lock); 1770 1788 1771 1789 socket_data->addr = addr; 1772 1790 socket_data->addrlen = addrlen; 1773 // send the packet 1791 1792 /* Send the packet */ 1774 1793 1775 1794 if (((rc = tcp_queue_packet(socket, socket_data, packet, 1)) != EOK) || … … 1785 1804 fibril_mutex_lock(&socket_data->operation.mutex); 1786 1805 fibril_rwlock_write_unlock(socket_data->local_lock); 1787 // send the packet 1806 1807 /* Send the packet */ 1788 1808 printf("connecting %d\n", packet_get_id(packet)); 1789 1809 tcp_send_packets(socket_data->device_id, packet); 1790 1810 1791 / / wait for a reply1811 /* Wait for a reply */ 1792 1812 fibril_condvar_wait(&socket_data->operation.condvar, 1793 1813 &socket_data->operation.mutex); … … 1805 1825 1806 1826 fibril_mutex_unlock(&socket_data->operation.mutex); 1807 1808 // return the result1809 1827 return rc; 1810 1828 } 1811 1829 1812 int 1813 tcp_queue_prepare_packet(socket_core_ref socket, 1830 int tcp_queue_prepare_packet(socket_core_ref socket, 1814 1831 tcp_socket_data_ref socket_data, packet_t packet, size_t data_length) 1815 1832 { … … 1821 1838 assert(socket->specific_data == socket_data); 1822 1839 1823 / / get tcp header1840 /* Get TCP header */ 1824 1841 header = (tcp_header_ref) packet_get_data(packet); 1825 1842 if (!header) … … 1835 1852 return tcp_release_and_return(packet, EINVAL); 1836 1853 1837 / / remember the outgoing FIN1854 /* Remember the outgoing FIN */ 1838 1855 if (header->finalize) 1839 1856 socket_data->fin_outgoing = socket_data->next_outgoing; … … 1842 1859 } 1843 1860 1844 int 1845 tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, 1861 int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, 1846 1862 packet_t packet, size_t data_length) 1847 1863 { … … 1865 1881 } 1866 1882 1867 packet_t 1868 tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_refsocket_data)1883 packet_t tcp_get_packets_to_send(socket_core_ref socket, tcp_socket_data_ref 1884 socket_data) 1869 1885 { 1870 1886 packet_t packet; … … 1883 1899 pq_get_order(packet, NULL, &data_length); 1884 1900 1885 // send only if fits into the window 1886 // respecting the possible overflow 1901 /* 1902 * Send only if fits into the window, respecting the possible 1903 * overflow. 1904 */ 1887 1905 if (!IS_IN_INTERVAL_OVERFLOW( 1888 1906 (uint32_t) socket_data->last_outgoing, … … 1909 1927 previous = copy; 1910 1928 packet = pq_next(packet); 1911 // overflow occurred ? 1929 1930 /* Overflow occurred? */ 1912 1931 if (!packet && 1913 1932 (socket_data->last_outgoing > socket_data->next_outgoing)) { 1914 1933 printf("gpts overflow\n"); 1915 / / continue from the beginning1934 /* Continue from the beginning */ 1916 1935 packet = socket_data->outgoing; 1917 1936 } … … 1922 1941 } 1923 1942 1924 packet_t 1925 tcp_send_prepare_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, 1926 packet_t packet, size_t data_length, size_t sequence_number) 1943 packet_t tcp_send_prepare_packet(socket_core_ref socket, tcp_socket_data_ref 1944 socket_data, packet_t packet, size_t data_length, size_t sequence_number) 1927 1945 { 1928 1946 tcp_header_ref header; … … 1934 1952 assert(socket->specific_data == socket_data); 1935 1953 1936 / / adjust the pseudo header1954 /* Adjust the pseudo header */ 1937 1955 rc = ip_client_set_pseudo_header_data_length(socket_data->pseudo_header, 1938 1956 socket_data->headerlen, packet_get_data_length(packet)); … … 1942 1960 } 1943 1961 1944 / / get the header1962 /* Get the header */ 1945 1963 header = (tcp_header_ref) packet_get_data(packet); 1946 1964 if (!header) { … … 1950 1968 assert(ntohl(header->sequence_number) == sequence_number); 1951 1969 1952 / / adjust the header1970 /* Adjust the header */ 1953 1971 if (socket_data->next_incoming) { 1954 1972 header->acknowledgement_number = … … 1958 1976 header->window = htons(socket_data->window); 1959 1977 1960 / / checksum1978 /* Checksum */ 1961 1979 header->checksum = 0; 1962 1980 checksum = compute_checksum(0, socket_data->pseudo_header, … … 1967 1985 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 1968 1986 1969 / / prepare the packet1987 /* Prepare the packet */ 1970 1988 rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0); 1971 1989 if (rc != EOK) { … … 1973 1991 return NULL; 1974 1992 } 1993 1975 1994 rc = tcp_prepare_timeout(tcp_timeout, socket, socket_data, 1976 1995 sequence_number, socket_data->state, socket_data->timeout, true); … … 1983 2002 } 1984 2003 1985 packet_t 1986 tcp_prepare_copy(socket_core_ref socket, tcp_socket_data_ref socket_data, 1987 packet_t packet, size_t data_length, size_t sequence_number) 2004 packet_t tcp_prepare_copy(socket_core_ref socket, tcp_socket_data_ref 2005 socket_data, packet_t packet, size_t data_length, size_t sequence_number) 1988 2006 { 1989 2007 packet_t copy; … … 1993 2011 assert(socket->specific_data == socket_data); 1994 2012 1995 / / make a copy of the packet2013 /* Make a copy of the packet */ 1996 2014 copy = packet_get_copy(tcp_globals.net_phone, packet); 1997 2015 if (!copy) … … 2014 2032 } 2015 2033 2016 void 2017 tcp_prepare_operation_header(socket_core_ref socket, 2034 void tcp_prepare_operation_header(socket_core_ref socket, 2018 2035 tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, 2019 2036 int finalize) … … 2032 2049 } 2033 2050 2034 int 2035 tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t), 2051 int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t), 2036 2052 socket_core_ref socket, tcp_socket_data_ref socket_data, 2037 2053 size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, … … 2045 2061 assert(socket->specific_data == socket_data); 2046 2062 2047 / / prepare the timeout with key bundle structure2063 /* Prepare the timeout with key bundle structure */ 2048 2064 operation_timeout = malloc(sizeof(*operation_timeout) + 2049 2065 socket->key_length + 1); … … 2060 2076 operation_timeout->state = state; 2061 2077 2062 / / copy the key2078 /* Copy the key */ 2063 2079 operation_timeout->key = ((char *) operation_timeout) + 2064 2080 sizeof(*operation_timeout); … … 2067 2083 operation_timeout->key[operation_timeout->key_length] = '\0'; 2068 2084 2069 / / prepare the timeouting thread2085 /* Prepare the timeouting thread */ 2070 2086 fibril = fibril_create(timeout_function, operation_timeout); 2071 2087 if (!fibril) { … … 2074 2090 } 2075 2091 // fibril_mutex_lock(&socket_data->operation.mutex); 2076 / / start the timeouting fibril2092 /* Start the timeout fibril */ 2077 2093 fibril_add_ready(fibril); 2078 2094 //socket_data->state = state; … … 2080 2096 } 2081 2097 2082 int 2083 tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 2084 size_t *addrlen) 2098 int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, 2099 int flags, size_t *addrlen) 2085 2100 { 2086 2101 socket_core_ref socket; … … 2093 2108 assert(local_sockets); 2094 2109 2095 / / find the socket2110 /* Find the socket */ 2096 2111 socket = socket_cores_find(local_sockets, socket_id); 2097 2112 if (!socket) 2098 2113 return ENOTSOCK; 2099 2114 2100 / / get the socket specific data2115 /* Get the socket specific data */ 2101 2116 if (!socket->specific_data) 2102 2117 return NO_DATA; … … 2104 2119 socket_data = (tcp_socket_data_ref) socket->specific_data; 2105 2120 2106 / / check state2121 /* Check state */ 2107 2122 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2108 2123 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) 2109 2124 return ENOTCONN; 2110 2125 2111 / / send the source address if desired2126 /* Send the source address if desired */ 2112 2127 if (addrlen) { 2113 2128 rc = data_reply(socket_data->addr, socket_data->addrlen); … … 2117 2132 } 2118 2133 2119 / / get the next received packet2134 /* Get the next received packet */ 2120 2135 packet_id = dyn_fifo_value(&socket->received); 2121 2136 if (packet_id < 0) … … 2126 2141 return rc; 2127 2142 2128 / / reply the packets2143 /* Reply the packets */ 2129 2144 rc = socket_reply_packets(packet, &length); 2130 2145 if (rc != EOK) 2131 2146 return rc; 2132 2147 2133 / / release the packet2148 /* Release the packet */ 2134 2149 dyn_fifo_pop(&socket->received); 2135 2150 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet)); 2136 // return the total length 2151 2152 /* Return the total length */ 2137 2153 return (int) length; 2138 2154 } 2139 2155 2140 int 2141 tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, 2142 size_t *data_fragment_size, int flags) 2156 int tcp_send_message(socket_cores_ref local_sockets, int socket_id, 2157 int fragments, size_t *data_fragment_size, int flags) 2143 2158 { 2144 2159 socket_core_ref socket; … … 2155 2170 assert(data_fragment_size); 2156 2171 2157 / / find the socket2172 /* Find the socket */ 2158 2173 socket = socket_cores_find(local_sockets, socket_id); 2159 2174 if (!socket) 2160 2175 return ENOTSOCK; 2161 2176 2162 / / get the socket specific data2177 /* Get the socket specific data */ 2163 2178 if (!socket->specific_data) 2164 2179 return NO_DATA; … … 2166 2181 socket_data = (tcp_socket_data_ref) socket->specific_data; 2167 2182 2168 / / check state2183 /* Check state */ 2169 2184 if ((socket_data->state != TCP_SOCKET_ESTABLISHED) && 2170 2185 (socket_data->state != TCP_SOCKET_CLOSE_WAIT)) … … 2181 2196 2182 2197 for (index = 0; index < fragments; index++) { 2183 / / read the data fragment2198 /* Read the data fragment */ 2184 2199 result = tl_socket_read_packet_data(tcp_globals.net_phone, 2185 2200 &packet, TCP_HEADER_SIZE, packet_dimension, … … 2189 2204 2190 2205 total_length = (size_t) result; 2191 // prefix the tcp header 2206 2207 /* Prefix the TCP header */ 2192 2208 header = PACKET_PREFIX(packet, tcp_header_t); 2193 2209 if (!header) … … 2200 2216 } 2201 2217 2202 / / flush packets2218 /* Flush packets */ 2203 2219 packet = tcp_get_packets_to_send(socket, socket_data); 2204 2220 fibril_rwlock_write_unlock(socket_data->local_lock); … … 2206 2222 2207 2223 if (packet) { 2208 / / send the packet2224 /* Send the packet */ 2209 2225 tcp_send_packets(socket_data->device_id, packet); 2210 2226 } … … 2221 2237 int rc; 2222 2238 2223 / / find the socket2239 /* Find the socket */ 2224 2240 socket = socket_cores_find(local_sockets, socket_id); 2225 2241 if (!socket) 2226 2242 return ENOTSOCK; 2227 2243 2228 / / get the socket specific data2244 /* Get the socket specific data */ 2229 2245 socket_data = (tcp_socket_data_ref) socket->specific_data; 2230 2246 assert(socket_data); 2231 2247 2232 / / check state2248 /* Check state */ 2233 2249 switch (socket_data->state) { 2234 2250 case TCP_SOCKET_ESTABLISHED: … … 2243 2259 2244 2260 default: 2245 / / just destroy2261 /* Just destroy */ 2246 2262 rc = socket_destroy(tcp_globals.net_phone, socket_id, 2247 2263 local_sockets, &tcp_globals.sockets, … … 2254 2270 } 2255 2271 2256 // send FIN 2257 // TODO should I wait to complete? 2258 2259 // create the notification packet 2272 /* 2273 * Send FIN. 2274 * TODO should I wait to complete? 2275 */ 2276 2277 /* Create the notification packet */ 2260 2278 rc = tcp_create_notification_packet(&packet, socket, socket_data, 0, 1); 2261 2279 if (rc != EOK) 2262 2280 return rc; 2263 2281 2264 / / send the packet2282 /* Send the packet */ 2265 2283 rc = tcp_queue_packet(socket, socket_data, packet, 1); 2266 2284 if (rc != EOK) 2267 2285 return rc; 2268 2286 2269 / / flush packets2287 /* Flush packets */ 2270 2288 packet = tcp_get_packets_to_send(socket, socket_data); 2271 2289 fibril_rwlock_write_unlock(socket_data->local_lock); … … 2273 2291 2274 2292 if (packet) { 2275 / / send the packet2293 /* Send the packet */ 2276 2294 tcp_send_packets(socket_data->device_id, packet); 2277 2295 } … … 2280 2298 } 2281 2299 2282 int 2283 tcp_create_notification_packet(packet_t *packet, socket_core_ref socket, 2300 int tcp_create_notification_packet(packet_t *packet, socket_core_ref socket, 2284 2301 tcp_socket_data_ref socket_data, int synchronize, int finalize) 2285 2302 { … … 2290 2307 assert(packet); 2291 2308 2292 / / get the device packet dimension2309 /* Get the device packet dimension */ 2293 2310 rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone, 2294 2311 &tcp_globals.dimensions, socket_data->device_id, &packet_dimension); … … 2296 2313 return rc; 2297 2314 2298 / / get a new packet2315 /* Get a new packet */ 2299 2316 *packet = packet_get_4_remote(tcp_globals.net_phone, TCP_HEADER_SIZE, 2300 2317 packet_dimension->addr_len, packet_dimension->prefix, … … 2304 2321 return ENOMEM; 2305 2322 2306 / / allocate space in the packet2323 /* Allocate space in the packet */ 2307 2324 header = PACKET_SUFFIX(*packet, tcp_header_t); 2308 2325 if (!header) … … 2315 2332 } 2316 2333 2317 int 2318 tcp_accept_message(socket_cores_ref local_sockets, int socket_id, 2334 int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, 2319 2335 int new_socket_id, size_t *data_fragment_size, size_t *addrlen) 2320 2336 { … … 2329 2345 assert(addrlen); 2330 2346 2331 / / find the socket2347 /* Find the socket */ 2332 2348 socket = socket_cores_find(local_sockets, socket_id); 2333 2349 if (!socket) 2334 2350 return ENOTSOCK; 2335 2351 2336 / / get the socket specific data2352 /* Get the socket specific data */ 2337 2353 socket_data = (tcp_socket_data_ref) socket->specific_data; 2338 2354 assert(socket_data); 2339 2355 2340 / / check state2356 /* Check state */ 2341 2357 if (socket_data->state != TCP_SOCKET_LISTEN) 2342 2358 return EINVAL; … … 2352 2368 return ENOTSOCK; 2353 2369 2354 / / get the socket specific data2370 /* Get the socket specific data */ 2355 2371 socket_data = (tcp_socket_data_ref) accepted->specific_data; 2356 2372 assert(socket_data); 2357 / / TODO can it be in another state?2373 /* TODO can it be in another state? */ 2358 2374 if (socket_data->state == TCP_SOCKET_ESTABLISHED) { 2359 2375 rc = data_reply(socket_data->addr, … … 2389 2405 } 2390 2406 2391 void 2392 tcp_free_socket_data(socket_core_ref socket) 2407 void tcp_free_socket_data(socket_core_ref socket) 2393 2408 { 2394 2409 tcp_socket_data_ref socket_data; … … 2398 2413 printf("destroy_socket %d\n", socket->socket_id); 2399 2414 2400 / / get the socket specific data2415 /* Get the socket specific data */ 2401 2416 socket_data = (tcp_socket_data_ref) socket->specific_data; 2402 2417 assert(socket_data); 2403 //free the pseudo header 2418 2419 /* Free the pseudo header */ 2404 2420 if (socket_data->pseudo_header) { 2405 2421 if (socket_data->headerlen) { … … 2410 2426 socket_data->pseudo_header = NULL; 2411 2427 } 2428 2412 2429 socket_data->headerlen = 0; 2413 // free the address 2430 2431 /* Free the address */ 2414 2432 if (socket_data->addr) { 2415 2433 if (socket_data->addrlen) { … … 2473 2491 2474 2492 /* 2475 2493 * Answer the message 2476 2494 */ 2477 2495 answer_call(callid, res, &answer, answer_count);
Note:
See TracChangeset
for help on using the changeset viewer.