Ignore:
File:
1 edited

Legend:

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

    rae481e0 rd9e14fa4  
    5252#define FRAGMENT_SIZE 1024
    5353
    54 #define MAX_BACKLOG 128
    55 
    5654/** Free ports pool start. */
    5755#define TCP_FREE_PORTS_START            1025
     
    6260static int last_used_port = TCP_FREE_PORTS_START - 1;
    6361static socket_ports_t gsock;
    64 
    65 static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
    6662
    6763void tcp_sock_init(void)
     
    9995{
    10096        tcp_sockdata_t *sock;
    101         socket_core_t *sock_core;
    10297        int sock_id;
    10398        int rc;
     
    111106        }
    112107
    113         fibril_mutex_initialize(&sock->lock);
    114108        sock->client = client;
    115109        sock->laddr.ipv4 = TCP_IPV4_ANY;
    116         sock->lconn = NULL;
    117         sock->backlog = 0;
    118         list_initialize(&sock->ready);
    119110
    120111        sock_id = SOCKET_GET_SOCKET_ID(call);
     
    124115                return;
    125116        }
    126 
    127         sock_core = socket_cores_find(&client->sockets, sock_id);
    128         assert(sock_core != NULL);
    129         sock->sock_core = sock_core;
    130117
    131118        refresh_answer(&answer, NULL);
     
    180167        socket_core_t *sock_core;
    181168        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;
    188169
    189170        log_msg(LVL_DEBUG, "tcp_sock_listen()");
     
    196177                return;
    197178        }
    198 
    199         if (backlog > MAX_BACKLOG)
    200                 backlog = MAX_BACKLOG;
    201179
    202180        sock_core = socket_cores_find(&client->sockets, socket_id);
     
    209187
    210188        /*
    211          * Prepare @c backlog listening connections.
     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.
    212196         */
    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);
     197        (void)backlog;
     198        (void)socket;
     199
    261200        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);
    262204}
    263205
     
    273215        tcp_sock_t lsocket;
    274216        tcp_sock_t fsocket;
    275         nic_device_id_t dev_id;
     217        device_id_t dev_id;
    276218        tcp_phdr_t *phdr;
    277219        size_t phdr_len;
     
    306248        }
    307249
    308         fibril_mutex_lock(&socket->lock);
    309 
    310250        if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
    311251                /* Find route to determine local IP address. */
     
    314254                    (void **)&phdr, &phdr_len);
    315255                if (rc != EOK) {
    316                         fibril_mutex_unlock(&socket->lock);
    317256                        async_answer_0(callid, rc);
    318257                        log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route.");
     
    330269        fsocket.port = uint16_t_be2host(addr->sin_port);
    331270
    332         trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
     271        trc = tcp_uc_open(&lsocket, &fsocket, ap_active, &socket->conn);
    333272
    334273        if (socket->conn != NULL)
    335274                socket->conn->name = (char *)"C";
    336 
    337         fibril_mutex_unlock(&socket->lock);
    338275
    339276        switch (trc) {
     
    368305        tcp_sock_t fsocket;
    369306        tcp_conn_t *conn;
    370         tcp_conn_t *rconn;
    371         tcp_sock_lconn_t *lconn;
    372307        int rc;
    373308
     
    384319
    385320        socket = (tcp_sockdata_t *)sock_core->specific_data;
    386         fibril_mutex_lock(&socket->lock);
    387321
    388322        log_msg(LVL_DEBUG, " - verify socket->conn");
    389323        if (socket->conn != NULL) {
    390                 fibril_mutex_unlock(&socket->lock);
    391324                async_answer_0(callid, EINVAL);
    392325                return;
    393326        }
    394327
    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 */
     328        log_msg(LVL_DEBUG, " - open connection");
    409329
    410330        lsocket.addr.ipv4 = TCP_IPV4_ANY;
     
    413333        fsocket.port = TCP_PORT_ANY;
    414334
    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 */
     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        }
    432357
    433358        log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
    434359        asocket = calloc(sizeof(tcp_sockdata_t), 1);
    435360        if (asocket == NULL) {
    436                 fibril_mutex_unlock(&socket->lock);
    437361                async_answer_0(callid, ENOMEM);
    438362                return;
    439363        }
    440364
    441         fibril_mutex_initialize(&asocket->lock);
    442365        asocket->client = client;
    443366        asocket->conn = conn;
     
    446369        rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
    447370        if (rc != EOK) {
    448                 fibril_mutex_unlock(&socket->lock);
    449371                async_answer_0(callid, rc);
    450372                return;
     
    463385        answer_call(callid, asock_core->socket_id, &answer, 3);
    464386
     387        /* Push one accept notification to client's queue */
     388        tcp_sock_notify_aconn(sock_core);
     389
    465390        /* Push one fragment notification to client's queue */
    466         log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
    467391        tcp_sock_notify_data(asock_core);
    468         fibril_mutex_unlock(&socket->lock);
     392        log_msg(LVL_DEBUG, "tcp_sock_accept(): notify aconn\n");
    469393}
    470394
     
    495419
    496420        socket = (tcp_sockdata_t *)sock_core->specific_data;
    497         fibril_mutex_lock(&socket->lock);
    498 
    499421        if (socket->conn == NULL) {
    500                 fibril_mutex_unlock(&socket->lock);
    501422                async_answer_0(callid, ENOTCONN);
    502423                return;
     
    505426        for (index = 0; index < fragments; index++) {
    506427                if (!async_data_write_receive(&wcallid, &length)) {
    507                         fibril_mutex_unlock(&socket->lock);
    508428                        async_answer_0(callid, EINVAL);
    509429                        return;
     
    515435                rc = async_data_write_finalize(wcallid, buffer, length);
    516436                if (rc != EOK) {
    517                         fibril_mutex_unlock(&socket->lock);
    518437                        async_answer_0(callid, rc);
    519438                        return;
     
    540459
    541460                if (rc != EOK) {
    542                         fibril_mutex_unlock(&socket->lock);
    543461                        async_answer_0(callid, rc);
    544462                        return;
     
    549467        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
    550468        answer_call(callid, EOK, &answer, 2);
    551         fibril_mutex_unlock(&socket->lock);
    552469}
    553470
     
    587504
    588505        socket = (tcp_sockdata_t *)sock_core->specific_data;
    589         fibril_mutex_lock(&socket->lock);
    590 
    591506        if (socket->conn == NULL) {
    592                 fibril_mutex_unlock(&socket->lock);
    593507                async_answer_0(callid, ENOTCONN);
    594508                return;
     
    618532        log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
    619533        if (rc != EOK) {
    620                 fibril_mutex_unlock(&socket->lock);
    621534                async_answer_0(callid, rc);
    622535                return;
     
    632545                log_msg(LVL_DEBUG, "addr read receive");
    633546                if (!async_data_read_receive(&rcallid, &addr_length)) {
    634                         fibril_mutex_unlock(&socket->lock);
    635547                        async_answer_0(callid, EINVAL);
    636548                        return;
     
    643555                rc = async_data_read_finalize(rcallid, &addr, addr_length);
    644556                if (rc != EOK) {
    645                         fibril_mutex_unlock(&socket->lock);
    646557                        async_answer_0(callid, EINVAL);
    647558                        return;
     
    651562        log_msg(LVL_DEBUG, "data read receive");
    652563        if (!async_data_read_receive(&rcallid, &length)) {
    653                 fibril_mutex_unlock(&socket->lock);
    654564                async_answer_0(callid, EINVAL);
    655565                return;
     
    670580        /* Push one fragment notification to client's queue */
    671581        tcp_sock_notify_data(sock_core);
    672         fibril_mutex_unlock(&socket->lock);
    673582}
    674583
     
    694603
    695604        socket = (tcp_sockdata_t *)sock_core->specific_data;
    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         }
     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);
    714616
    715617        rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock,
    716618            tcp_free_sock_data);
    717619        if (rc != EOK) {
    718                 fibril_mutex_unlock(&socket->lock);
    719                 async_answer_0(callid, rc);
    720                 return;
    721         }
    722 
    723         fibril_mutex_unlock(&socket->lock);
     620                async_answer_0(callid, rc);
     621                return;
     622        }
     623
    724624        async_answer_0(callid, EOK);
    725625}
     
    735635        log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
    736636        async_answer_0(callid, ENOTSUP);
    737 }
    738 
    739 /** Called when connection state changes. */
    740 static 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);
    764637}
    765638
Note: See TracChangeset for help on using the changeset viewer.