Changeset 97c7682 in mainline for uspace/srv/net/tcp/sock.c
- Timestamp:
- 2012-07-14T11:18:40Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 804d9b6
- Parents:
- 0747468 (diff), f0348c8 (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 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tcp/sock.c
r0747468 r97c7682 38 38 #include <async.h> 39 39 #include <errno.h> 40 #include <inet/inet.h> 40 41 #include <io/log.h> 41 #include <ip _client.h>42 #include <ipc/services.h> 42 43 #include <ipc/socket.h> 43 #include <net/modules.h>44 44 #include <net/socket.h> 45 #include <ns.h> 45 46 46 47 #include "sock.h" … … 50 51 #include "ucall.h" 51 52 52 #define FRAGMENT_SIZE 102453 54 53 #define MAX_BACKLOG 128 55 54 … … 63 62 static socket_ports_t gsock; 64 63 64 static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg); 65 65 static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg); 66 67 void tcp_sock_init(void) 66 static int tcp_sock_recv_fibril(void *arg); 67 68 int tcp_sock_init(void) 68 69 { 69 70 socket_ports_initialize(&gsock); 71 72 async_set_client_connection(tcp_sock_connection); 73 74 int rc = service_register(SERVICE_TCP); 75 if (rc != EOK) 76 return EEXIST; 77 78 return EOK; 70 79 } 71 80 … … 76 85 socket = (tcp_sockdata_t *)sock_core->specific_data; 77 86 (void)socket; 87 88 /* XXX We need to initiate connection cleanup here */ 78 89 } 79 90 … … 83 94 async_exch_t *exch = async_exchange_begin(sock_core->sess); 84 95 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id, 85 FRAGMENT_SIZE, 0, 0, 1);96 TCP_SOCK_FRAGMENT_SIZE, 0, 0, 1); 86 97 async_exchange_end(exch); 87 98 } … … 92 103 async_exch_t *exch = async_exchange_begin(lsock_core->sess); 93 104 async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id, 94 FRAGMENT_SIZE, 0, 0, 0);105 TCP_SOCK_FRAGMENT_SIZE, 0, 0, 0); 95 106 async_exchange_end(exch); 96 107 } 97 108 109 static int tcp_sock_create(tcp_client_t *client, tcp_sockdata_t **rsock) 110 { 111 tcp_sockdata_t *sock; 112 113 log_msg(LVL_DEBUG, "tcp_sock_create()"); 114 *rsock = NULL; 115 116 sock = calloc(sizeof(tcp_sockdata_t), 1); 117 if (sock == NULL) 118 return ENOMEM; 119 120 fibril_mutex_initialize(&sock->lock); 121 sock->client = client; 122 123 sock->recv_buffer_used = 0; 124 sock->recv_error = TCP_EOK; 125 fibril_mutex_initialize(&sock->recv_buffer_lock); 126 fibril_condvar_initialize(&sock->recv_buffer_cv); 127 list_initialize(&sock->ready); 128 129 *rsock = sock; 130 return EOK; 131 } 132 133 static void tcp_sock_uncreate(tcp_sockdata_t *sock) 134 { 135 log_msg(LVL_DEBUG, "tcp_sock_uncreate()"); 136 free(sock); 137 } 138 139 static int tcp_sock_finish_setup(tcp_sockdata_t *sock, int *sock_id) 140 { 141 socket_core_t *sock_core; 142 int rc; 143 144 log_msg(LVL_DEBUG, "tcp_sock_finish_setup()"); 145 146 sock->recv_fibril = fibril_create(tcp_sock_recv_fibril, sock); 147 if (sock->recv_fibril == 0) 148 return ENOMEM; 149 150 rc = socket_create(&sock->client->sockets, sock->client->sess, 151 sock, sock_id); 152 153 if (rc != EOK) { 154 fibril_destroy(sock->recv_fibril); 155 sock->recv_fibril = 0; 156 return rc; 157 } 158 159 sock_core = socket_cores_find(&sock->client->sockets, *sock_id); 160 assert(sock_core != NULL); 161 sock->sock_core = sock_core; 162 163 return EOK; 164 } 165 98 166 static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call) 99 167 { 100 168 tcp_sockdata_t *sock; 101 socket_core_t *sock_core;102 169 int sock_id; 103 170 int rc; … … 105 172 106 173 log_msg(LVL_DEBUG, "tcp_sock_socket()"); 107 sock = calloc(sizeof(tcp_sockdata_t), 1); 108 if (sock == NULL) { 109 async_answer_0(callid, ENOMEM); 110 return; 111 } 112 113 fibril_mutex_initialize(&sock->lock); 114 sock->client = client; 174 175 rc = tcp_sock_create(client, &sock); 176 if (rc != EOK) { 177 async_answer_0(callid, rc); 178 return; 179 } 180 115 181 sock->laddr.ipv4 = TCP_IPV4_ANY; 116 182 sock->lconn = NULL; 117 183 sock->backlog = 0; 118 list_initialize(&sock->ready);119 184 120 185 sock_id = SOCKET_GET_SOCKET_ID(call); 121 rc = socket_create(&client->sockets, client->sess,sock, &sock_id);186 rc = tcp_sock_finish_setup(sock, &sock_id); 122 187 if (rc != EOK) { 188 tcp_sock_uncreate(sock); 123 189 async_answer_0(callid, rc); 124 190 return; 125 191 } 126 192 127 sock_core = socket_cores_find(&client->sockets, sock_id);128 assert(sock_core != NULL);129 sock->sock_core = sock_core;130 131 refresh_answer(&answer, NULL);132 193 SOCKET_SET_SOCKET_ID(answer, sock_id); 133 194 134 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);195 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE); 135 196 SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t)); 136 answer_call(callid, EOK, &answer, 3); 197 198 async_answer_3(callid, EOK, IPC_GET_ARG1(answer), 199 IPC_GET_ARG2(answer), IPC_GET_ARG3(answer)); 137 200 } 138 201 … … 273 336 tcp_sock_t lsocket; 274 337 tcp_sock_t fsocket; 275 nic_device_id_t dev_id;276 tcp_phdr_t *phdr;277 size_t phdr_len;278 338 279 339 log_msg(LVL_DEBUG, "tcp_sock_connect()"); … … 309 369 310 370 if (socket->laddr.ipv4 == TCP_IPV4_ANY) { 311 /* Find route to determine local IP address. */ 312 rc = ip_get_route_req(ip_sess, IPPROTO_TCP, 313 (struct sockaddr *)addr, sizeof(*addr), &dev_id, 314 (void **)&phdr, &phdr_len); 371 /* Determine local IP address */ 372 inet_addr_t loc_addr, rem_addr; 373 374 rem_addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr); 375 rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr); 315 376 if (rc != EOK) { 316 377 fibril_mutex_unlock(&socket->lock); 317 378 async_answer_0(callid, rc); 318 log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route."); 379 log_msg(LVL_DEBUG, "tcp_sock_connect: Failed to " 380 "determine local address."); 319 381 return; 320 382 } 321 383 322 socket->laddr.ipv4 = uint32_t_be2host(phdr->src_addr);384 socket->laddr.ipv4 = loc_addr.ipv4; 323 385 log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4); 324 free(phdr);325 386 } 326 387 … … 348 409 } 349 410 411 if (rc == EOK) 412 fibril_add_ready(socket->recv_fibril); 413 350 414 async_answer_0(callid, rc); 351 352 /* Push one fragment notification to client's queue */353 tcp_sock_notify_data(sock_core);354 log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");355 415 } 356 416 … … 361 421 int asock_id; 362 422 socket_core_t *sock_core; 363 socket_core_t *asock_core;364 423 tcp_sockdata_t *socket; 365 424 tcp_sockdata_t *asocket; … … 431 490 /* Allocate socket for accepted connection */ 432 491 433 log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n"); 434 asocket = calloc(sizeof(tcp_sockdata_t), 1); 435 if (asocket == NULL) { 436 fibril_mutex_unlock(&socket->lock); 437 async_answer_0(callid, ENOMEM); 438 return; 439 } 440 441 fibril_mutex_initialize(&asocket->lock); 442 asocket->client = client; 492 rc = tcp_sock_create(client, &asocket); 493 if (rc != EOK) { 494 fibril_mutex_unlock(&socket->lock); 495 async_answer_0(callid, rc); 496 return; 497 } 498 443 499 asocket->conn = conn; 444 500 log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n"); 445 501 446 rc = socket_create(&client->sockets, client->sess,asocket, &asock_id);502 rc = tcp_sock_finish_setup(asocket, &asock_id); 447 503 if (rc != EOK) { 504 tcp_sock_uncreate(asocket); 448 505 fibril_mutex_unlock(&socket->lock); 449 506 async_answer_0(callid, rc); 450 507 return; 451 508 } 509 510 fibril_add_ready(asocket->recv_fibril); 511 452 512 log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n"); 453 513 454 asock_core = socket_cores_find(&client->sockets, asock_id); 455 assert(asock_core != NULL); 456 457 refresh_answer(&answer, NULL); 458 459 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE); 514 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE); 460 515 SOCKET_SET_SOCKET_ID(answer, asock_id); 461 516 SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in)); 462 463 answer_call(callid, asock_core->socket_id, &answer, 3); 464 517 518 async_answer_3(callid, asocket->sock_core->socket_id, 519 IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), 520 IPC_GET_ARG3(answer)); 521 465 522 /* Push one fragment notification to client's queue */ 466 523 log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n"); 467 tcp_sock_notify_data(asock_core);468 524 fibril_mutex_unlock(&socket->lock); 469 525 } … … 479 535 ipc_callid_t wcallid; 480 536 size_t length; 481 uint8_t buffer[ FRAGMENT_SIZE];537 uint8_t buffer[TCP_SOCK_FRAGMENT_SIZE]; 482 538 tcp_error_t trc; 483 539 int rc; … … 510 566 } 511 567 512 if (length > FRAGMENT_SIZE)513 length = FRAGMENT_SIZE;568 if (length > TCP_SOCK_FRAGMENT_SIZE) 569 length = TCP_SOCK_FRAGMENT_SIZE; 514 570 515 571 rc = async_data_write_finalize(wcallid, buffer, length); … … 546 602 } 547 603 548 refresh_answer(&answer, NULL); 549 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE); 550 answer_call(callid, EOK, &answer, 2); 604 IPC_SET_ARG1(answer, 0); 605 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE); 606 async_answer_2(callid, EOK, IPC_GET_ARG1(answer), 607 IPC_GET_ARG2(answer)); 551 608 fibril_mutex_unlock(&socket->lock); 552 609 } … … 567 624 ipc_call_t answer; 568 625 ipc_callid_t rcallid; 569 uint8_t buffer[FRAGMENT_SIZE];570 626 size_t data_len; 571 xflags_t xflags;572 tcp_error_t trc;573 627 struct sockaddr_in addr; 574 628 tcp_sock_t *rsock; … … 597 651 (void)flags; 598 652 599 trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len, 600 &xflags); 601 log_msg(LVL_DEBUG, "**** tcp_uc_receive done"); 602 603 switch (trc) { 653 log_msg(LVL_DEBUG, "tcp_sock_recvfrom(): lock recv_buffer_lock"); 654 fibril_mutex_lock(&socket->recv_buffer_lock); 655 while (socket->recv_buffer_used == 0 && socket->recv_error == TCP_EOK) { 656 log_msg(LVL_DEBUG, "wait for recv_buffer_cv + recv_buffer_used != 0"); 657 fibril_condvar_wait(&socket->recv_buffer_cv, 658 &socket->recv_buffer_lock); 659 } 660 661 log_msg(LVL_DEBUG, "Got data in sock recv_buffer"); 662 663 data_len = socket->recv_buffer_used; 664 rc = socket->recv_error; 665 666 switch (socket->recv_error) { 604 667 case TCP_EOK: 605 668 rc = EOK; … … 616 679 } 617 680 618 log_msg(LVL_DEBUG, "**** tcp_uc_receive-> %d", rc);681 log_msg(LVL_DEBUG, "**** recv result -> %d", rc); 619 682 if (rc != EOK) { 683 fibril_mutex_unlock(&socket->recv_buffer_lock); 620 684 fibril_mutex_unlock(&socket->lock); 621 685 async_answer_0(callid, rc); … … 632 696 log_msg(LVL_DEBUG, "addr read receive"); 633 697 if (!async_data_read_receive(&rcallid, &addr_length)) { 698 fibril_mutex_unlock(&socket->recv_buffer_lock); 634 699 fibril_mutex_unlock(&socket->lock); 635 700 async_answer_0(callid, EINVAL); … … 643 708 rc = async_data_read_finalize(rcallid, &addr, addr_length); 644 709 if (rc != EOK) { 710 fibril_mutex_unlock(&socket->recv_buffer_lock); 645 711 fibril_mutex_unlock(&socket->lock); 646 712 async_answer_0(callid, EINVAL); … … 651 717 log_msg(LVL_DEBUG, "data read receive"); 652 718 if (!async_data_read_receive(&rcallid, &length)) { 719 fibril_mutex_unlock(&socket->recv_buffer_lock); 653 720 fibril_mutex_unlock(&socket->lock); 654 721 async_answer_0(callid, EINVAL); … … 660 727 661 728 log_msg(LVL_DEBUG, "data read finalize"); 662 rc = async_data_read_finalize(rcallid, buffer, length); 729 rc = async_data_read_finalize(rcallid, socket->recv_buffer, length); 730 731 socket->recv_buffer_used -= length; 732 log_msg(LVL_DEBUG, "tcp_sock_recvfrom: %zu left in buffer", 733 socket->recv_buffer_used); 734 if (socket->recv_buffer_used > 0) { 735 memmove(socket->recv_buffer, socket->recv_buffer + length, 736 socket->recv_buffer_used); 737 tcp_sock_notify_data(socket->sock_core); 738 } 739 740 fibril_condvar_broadcast(&socket->recv_buffer_cv); 663 741 664 742 if (length < data_len && rc == EOK) … … 666 744 667 745 SOCKET_SET_READ_DATA_LENGTH(answer, length); 668 answer_call(callid, EOK, &answer, 1); 669 670 /* Push one fragment notification to client's queue */ 671 tcp_sock_notify_data(sock_core); 746 async_answer_1(callid, EOK, IPC_GET_ARG1(answer)); 747 748 fibril_mutex_unlock(&socket->recv_buffer_lock); 672 749 fibril_mutex_unlock(&socket->lock); 673 750 } … … 680 757 tcp_error_t trc; 681 758 int rc; 682 uint8_t buffer[FRAGMENT_SIZE];683 size_t data_len;684 xflags_t xflags;685 759 686 760 log_msg(LVL_DEBUG, "tcp_sock_close()"); … … 703 777 return; 704 778 } 705 706 /* Drain incoming data. This should really be done in the background. */ 707 do { 708 trc = tcp_uc_receive(socket->conn, buffer, 709 FRAGMENT_SIZE, &data_len, &xflags); 710 } while (trc == TCP_EOK); 711 712 tcp_uc_delete(socket->conn); 713 } 714 715 rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock, 779 } 780 781 rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock, 716 782 tcp_free_sock_data); 717 783 if (rc != EOK) { … … 764 830 } 765 831 766 int tcp_sock_connection(async_sess_t *sess, ipc_callid_t iid, ipc_call_t icall) 832 static int tcp_sock_recv_fibril(void *arg) 833 { 834 tcp_sockdata_t *sock = (tcp_sockdata_t *)arg; 835 size_t data_len; 836 xflags_t xflags; 837 tcp_error_t trc; 838 839 log_msg(LVL_DEBUG, "tcp_sock_recv_fibril()"); 840 841 while (true) { 842 log_msg(LVL_DEBUG, "call tcp_uc_receive()"); 843 fibril_mutex_lock(&sock->recv_buffer_lock); 844 while (sock->recv_buffer_used != 0) 845 fibril_condvar_wait(&sock->recv_buffer_cv, 846 &sock->recv_buffer_lock); 847 848 trc = tcp_uc_receive(sock->conn, sock->recv_buffer, 849 TCP_SOCK_FRAGMENT_SIZE, &data_len, &xflags); 850 851 if (trc != TCP_EOK) { 852 sock->recv_error = trc; 853 fibril_condvar_broadcast(&sock->recv_buffer_cv); 854 fibril_mutex_unlock(&sock->recv_buffer_lock); 855 tcp_sock_notify_data(sock->sock_core); 856 break; 857 } 858 859 log_msg(LVL_DEBUG, "got data - broadcast recv_buffer_cv"); 860 861 sock->recv_buffer_used = data_len; 862 fibril_condvar_broadcast(&sock->recv_buffer_cv); 863 fibril_mutex_unlock(&sock->recv_buffer_lock); 864 tcp_sock_notify_data(sock->sock_core); 865 } 866 867 tcp_uc_delete(sock->conn); 868 869 return 0; 870 } 871 872 static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 767 873 { 768 874 ipc_callid_t callid; … … 773 879 async_answer_0(iid, EOK); 774 880 775 client.sess = sess;881 client.sess = async_callback_receive(EXCHANGE_SERIALIZE); 776 882 socket_cores_initialize(&client.sockets); 777 883 … … 825 931 } 826 932 827 return EOK; 933 /* Clean up */ 934 log_msg(LVL_DEBUG, "tcp_sock_connection: Clean up"); 935 async_hangup(client.sess); 936 socket_cores_release(NULL, &client.sockets, &gsock, tcp_free_sock_data); 828 937 } 829 938
Note:
See TracChangeset
for help on using the changeset viewer.