Changeset 7943c43 in mainline for uspace/srv/net/tl/tcp/sock.c


Ignore:
Timestamp:
2012-01-16T22:45:38Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
32817cc, 3fe58d3c
Parents:
9117ef9b (diff), 3ea725e (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.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/tcp/sock.c

    r9117ef9b r7943c43  
    5252#define FRAGMENT_SIZE 1024
    5353
     54#define MAX_BACKLOG 128
     55
    5456/** Free ports pool start. */
    5557#define TCP_FREE_PORTS_START            1025
     
    6062static int last_used_port = TCP_FREE_PORTS_START - 1;
    6163static socket_ports_t gsock;
     64
     65static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
    6266
    6367void tcp_sock_init(void)
     
    9599{
    96100        tcp_sockdata_t *sock;
     101        socket_core_t *sock_core;
    97102        int sock_id;
    98103        int rc;
     
    106111        }
    107112
     113        fibril_mutex_initialize(&sock->lock);
    108114        sock->client = client;
    109115        sock->laddr.ipv4 = TCP_IPV4_ANY;
     116        sock->lconn = NULL;
     117        sock->backlog = 0;
     118        list_initialize(&sock->ready);
    110119
    111120        sock_id = SOCKET_GET_SOCKET_ID(call);
     
    115124                return;
    116125        }
     126
     127        sock_core = socket_cores_find(&client->sockets, sock_id);
     128        assert(sock_core != NULL);
     129        sock->sock_core = sock_core;
    117130
    118131        refresh_answer(&answer, NULL);
     
    167180        socket_core_t *sock_core;
    168181        tcp_sockdata_t *socket;
     182        tcp_error_t trc;
     183        tcp_sock_t lsocket;
     184        tcp_sock_t fsocket;
     185        tcp_conn_t *conn;
     186        tcp_sock_lconn_t *lconn;
     187        int i;
    169188
    170189        log_msg(LVL_DEBUG, "tcp_sock_listen()");
     
    177196                return;
    178197        }
     198
     199        if (backlog > MAX_BACKLOG)
     200                backlog = MAX_BACKLOG;
    179201
    180202        sock_core = socket_cores_find(&client->sockets, socket_id);
     
    187209
    188210        /*
    189          * XXX We do not do anything and defer action to accept().
    190          * This is a slight difference in semantics, but most servers
    191          * would just listen() and immediately accept() in a loop.
    192          *
    193          * The only difference is that there is a window between
    194          * listen() and accept() or two accept()s where we refuse
    195          * connections.
     211         * Prepare @c backlog listening connections.
    196212         */
    197         (void)backlog;
    198         (void)socket;
    199 
     213        fibril_mutex_lock(&socket->lock);
     214
     215        socket->backlog = backlog;
     216        socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
     217        if (socket->lconn == NULL) {
     218                fibril_mutex_unlock(&socket->lock);
     219                async_answer_0(callid, ENOMEM);
     220                return;
     221        }
     222
     223        log_msg(LVL_DEBUG, " - open connections");
     224
     225        lsocket.addr.ipv4 = TCP_IPV4_ANY;
     226        lsocket.port = sock_core->port;
     227        fsocket.addr.ipv4 = TCP_IPV4_ANY;
     228        fsocket.port = TCP_PORT_ANY;
     229
     230        for (i = 0; i < backlog; i++) {
     231
     232                lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
     233                if (lconn == NULL) {
     234                        /* XXX Clean up */
     235                        fibril_mutex_unlock(&socket->lock);
     236                        async_answer_0(callid, ENOMEM);
     237                        return;
     238                }
     239
     240                trc = tcp_uc_open(&lsocket, &fsocket, ap_passive,
     241                    tcp_open_nonblock, &conn);
     242                if (conn == NULL) {
     243                        /* XXX Clean up */
     244                        fibril_mutex_unlock(&socket->lock);
     245                        async_answer_0(callid, ENOMEM);
     246                        return;
     247                }
     248
     249                tcp_uc_set_cstate_cb(conn, tcp_sock_cstate_cb, lconn);
     250
     251                assert(trc == TCP_EOK);
     252                conn->name = (char *)"S";
     253
     254                lconn->conn = conn;
     255                lconn->socket = socket;
     256                link_initialize(&lconn->ready_list);
     257                socket->lconn[i] = lconn;
     258        }
     259
     260        fibril_mutex_unlock(&socket->lock);
    200261        async_answer_0(callid, EOK);
    201         log_msg(LVL_DEBUG, "tcp_sock_listen(): notify data\n");
    202         /* Push one accept notification to client's queue */
    203         tcp_sock_notify_aconn(sock_core);
    204262}
    205263
     
    248306        }
    249307
     308        fibril_mutex_lock(&socket->lock);
     309
    250310        if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
    251311                /* Find route to determine local IP address. */
     
    254314                    (void **)&phdr, &phdr_len);
    255315                if (rc != EOK) {
     316                        fibril_mutex_unlock(&socket->lock);
    256317                        async_answer_0(callid, rc);
    257318                        log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route.");
     
    269330        fsocket.port = uint16_t_be2host(addr->sin_port);
    270331
    271         trc = tcp_uc_open(&lsocket, &fsocket, ap_active, &socket->conn);
     332        trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
    272333
    273334        if (socket->conn != NULL)
    274335                socket->conn->name = (char *)"C";
     336
     337        fibril_mutex_unlock(&socket->lock);
    275338
    276339        switch (trc) {
     
    305368        tcp_sock_t fsocket;
    306369        tcp_conn_t *conn;
     370        tcp_conn_t *rconn;
     371        tcp_sock_lconn_t *lconn;
    307372        int rc;
    308373
     
    319384
    320385        socket = (tcp_sockdata_t *)sock_core->specific_data;
     386        fibril_mutex_lock(&socket->lock);
    321387
    322388        log_msg(LVL_DEBUG, " - verify socket->conn");
    323389        if (socket->conn != NULL) {
     390                fibril_mutex_unlock(&socket->lock);
    324391                async_answer_0(callid, EINVAL);
    325392                return;
    326393        }
    327394
    328         log_msg(LVL_DEBUG, " - open connection");
     395        if (list_empty(&socket->ready)) {
     396                fibril_mutex_unlock(&socket->lock);
     397                async_answer_0(callid, ENOENT);
     398                return;
     399        }
     400
     401        lconn = list_get_instance(list_first(&socket->ready),
     402            tcp_sock_lconn_t, ready_list);
     403        list_remove(&lconn->ready_list);
     404
     405        conn = lconn->conn;
     406        tcp_uc_set_cstate_cb(conn, NULL, NULL);
     407
     408        /* Replenish listening connection */
    329409
    330410        lsocket.addr.ipv4 = TCP_IPV4_ANY;
     
    333413        fsocket.port = TCP_PORT_ANY;
    334414
    335         trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, &conn);
    336         if (conn != NULL)
    337                 conn->name = (char *)"S";
    338 
    339         log_msg(LVL_DEBUG, " - decode TCP return code");
    340 
    341         switch (trc) {
    342         case TCP_EOK:
    343                 rc = EOK;
    344                 break;
    345         case TCP_ERESET:
    346                 rc = ECONNABORTED;
    347                 break;
    348         default:
    349                 assert(false);
    350         }
    351 
    352         log_msg(LVL_DEBUG, " - check TCP return code");
    353         if (rc != EOK) {
    354                 async_answer_0(callid, rc);
    355                 return;
    356         }
     415        trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock,
     416            &rconn);
     417        if (rconn == NULL) {
     418                /* XXX Clean up */
     419                fibril_mutex_unlock(&socket->lock);
     420                async_answer_0(callid, ENOMEM);
     421                return;
     422        }
     423
     424        tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn);
     425
     426        assert(trc == TCP_EOK);
     427        rconn->name = (char *)"S";
     428
     429        lconn->conn = rconn;
     430
     431        /* Allocate socket for accepted connection */
    357432
    358433        log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
    359434        asocket = calloc(sizeof(tcp_sockdata_t), 1);
    360435        if (asocket == NULL) {
     436                fibril_mutex_unlock(&socket->lock);
    361437                async_answer_0(callid, ENOMEM);
    362438                return;
    363439        }
    364440
     441        fibril_mutex_initialize(&asocket->lock);
    365442        asocket->client = client;
    366443        asocket->conn = conn;
     
    369446        rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
    370447        if (rc != EOK) {
     448                fibril_mutex_unlock(&socket->lock);
    371449                async_answer_0(callid, rc);
    372450                return;
     
    385463        answer_call(callid, asock_core->socket_id, &answer, 3);
    386464
    387         /* Push one accept notification to client's queue */
    388         tcp_sock_notify_aconn(sock_core);
    389 
    390465        /* Push one fragment notification to client's queue */
     466        log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
    391467        tcp_sock_notify_data(asock_core);
    392         log_msg(LVL_DEBUG, "tcp_sock_accept(): notify aconn\n");
     468        fibril_mutex_unlock(&socket->lock);
    393469}
    394470
     
    419495
    420496        socket = (tcp_sockdata_t *)sock_core->specific_data;
     497        fibril_mutex_lock(&socket->lock);
     498
    421499        if (socket->conn == NULL) {
     500                fibril_mutex_unlock(&socket->lock);
    422501                async_answer_0(callid, ENOTCONN);
    423502                return;
     
    426505        for (index = 0; index < fragments; index++) {
    427506                if (!async_data_write_receive(&wcallid, &length)) {
     507                        fibril_mutex_unlock(&socket->lock);
    428508                        async_answer_0(callid, EINVAL);
    429509                        return;
     
    435515                rc = async_data_write_finalize(wcallid, buffer, length);
    436516                if (rc != EOK) {
     517                        fibril_mutex_unlock(&socket->lock);
    437518                        async_answer_0(callid, rc);
    438519                        return;
     
    459540
    460541                if (rc != EOK) {
     542                        fibril_mutex_unlock(&socket->lock);
    461543                        async_answer_0(callid, rc);
    462544                        return;
     
    467549        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
    468550        answer_call(callid, EOK, &answer, 2);
     551        fibril_mutex_unlock(&socket->lock);
    469552}
    470553
     
    504587
    505588        socket = (tcp_sockdata_t *)sock_core->specific_data;
     589        fibril_mutex_lock(&socket->lock);
     590
    506591        if (socket->conn == NULL) {
     592                fibril_mutex_unlock(&socket->lock);
    507593                async_answer_0(callid, ENOTCONN);
    508594                return;
     
    532618        log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
    533619        if (rc != EOK) {
     620                fibril_mutex_unlock(&socket->lock);
    534621                async_answer_0(callid, rc);
    535622                return;
     
    545632                log_msg(LVL_DEBUG, "addr read receive");
    546633                if (!async_data_read_receive(&rcallid, &addr_length)) {
     634                        fibril_mutex_unlock(&socket->lock);
    547635                        async_answer_0(callid, EINVAL);
    548636                        return;
     
    555643                rc = async_data_read_finalize(rcallid, &addr, addr_length);
    556644                if (rc != EOK) {
     645                        fibril_mutex_unlock(&socket->lock);
    557646                        async_answer_0(callid, EINVAL);
    558647                        return;
     
    562651        log_msg(LVL_DEBUG, "data read receive");
    563652        if (!async_data_read_receive(&rcallid, &length)) {
     653                fibril_mutex_unlock(&socket->lock);
    564654                async_answer_0(callid, EINVAL);
    565655                return;
     
    580670        /* Push one fragment notification to client's queue */
    581671        tcp_sock_notify_data(sock_core);
     672        fibril_mutex_unlock(&socket->lock);
    582673}
    583674
     
    603694
    604695        socket = (tcp_sockdata_t *)sock_core->specific_data;
    605         rc = tcp_uc_close(socket->conn);
    606         if (rc != EOK) {
    607                 async_answer_0(callid, rc);
    608                 return;
    609         }
    610 
    611         /* Drain incoming data. This should really be done in the background. */
    612         do {
    613                 trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE,
    614                     &data_len, &xflags);
    615         } while (trc == TCP_EOK);
     696        fibril_mutex_lock(&socket->lock);
     697
     698        if (socket->conn != NULL) {
     699                trc = tcp_uc_close(socket->conn);
     700                if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
     701                        fibril_mutex_unlock(&socket->lock);
     702                        async_answer_0(callid, EBADF);
     703                        return;
     704                }
     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        }
    616714
    617715        rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock,
    618716            tcp_free_sock_data);
    619717        if (rc != EOK) {
     718                fibril_mutex_unlock(&socket->lock);
    620719                async_answer_0(callid, rc);
    621720                return;
    622721        }
    623722
     723        fibril_mutex_unlock(&socket->lock);
    624724        async_answer_0(callid, EOK);
    625725}
     
    635735        log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
    636736        async_answer_0(callid, ENOTSUP);
     737}
     738
     739/** Called when connection state changes. */
     740static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg)
     741{
     742        tcp_conn_status_t cstatus;
     743        tcp_sock_lconn_t *lconn = (tcp_sock_lconn_t *)arg;
     744        tcp_sockdata_t *socket = lconn->socket;
     745
     746        log_msg(LVL_DEBUG, "tcp_sock_cstate_cb()");
     747        fibril_mutex_lock(&socket->lock);
     748        assert(conn == lconn->conn);
     749
     750        tcp_uc_status(conn, &cstatus);
     751        if (cstatus.cstate != st_established) {
     752                fibril_mutex_unlock(&socket->lock);
     753                return;
     754        }
     755
     756        assert_link_not_used(&lconn->ready_list);
     757        list_append(&lconn->ready_list, &socket->ready);
     758
     759        log_msg(LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
     760
     761        /* Push one accept notification to client's queue */
     762        tcp_sock_notify_aconn(socket->sock_core);
     763        fibril_mutex_unlock(&socket->lock);
    637764}
    638765
Note: See TracChangeset for help on using the changeset viewer.