Changeset ae481e0 in mainline


Ignore:
Timestamp:
2011-12-29T14:47:00Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2943db4
Parents:
827ec41
Message:

Implement listening backlog.

Location:
uspace
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/websrv/websrv.c

    r827ec41 rae481e0  
    4949
    5050#define PORT_NUMBER 8080
     51#define BACKLOG_SIZE 3
    5152
    5253#define WEB_ROOT "/data/web"
     
    275276        }
    276277
    277         rc = listen(listen_sd, 1);
     278        rc = listen(listen_sd, BACKLOG_SIZE);
    278279        if (rc != EOK) {
    279280                printf("Error calling listen() (%d).\n", rc);
  • uspace/srv/net/tl/tcp/conn.c

    r827ec41 rae481e0  
    121121        fibril_condvar_initialize(&conn->cstate_cv);
    122122
     123        conn->cstate_cb = NULL;
     124
    123125        conn->cstate = st_listen;
    124126        conn->reset = false;
     
    243245        tcp_cstate_t old_state;
    244246
     247        log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
     248
    245249        old_state = conn->cstate;
    246250        conn->cstate = nstate;
    247251        fibril_condvar_broadcast(&conn->cstate_cv);
     252
     253        /* Run user callback function */
     254        if (conn->cstate_cb != NULL) {
     255                log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
     256                conn->cstate_cb(conn, conn->cstate_cb_arg);
     257        } else {
     258                log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
     259        }
    248260
    249261        assert(old_state != st_closed);
  • uspace/srv/net/tl/tcp/sock.c

    r827ec41 rae481e0  
    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;
     696        fibril_mutex_lock(&socket->lock);
    605697
    606698        if (socket->conn != NULL) {
    607699                trc = tcp_uc_close(socket->conn);
    608700                if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
     701                        fibril_mutex_unlock(&socket->lock);
    609702                        async_answer_0(callid, EBADF);
    610703                        return;
     
    623716            tcp_free_sock_data);
    624717        if (rc != EOK) {
     718                fibril_mutex_unlock(&socket->lock);
    625719                async_answer_0(callid, rc);
    626720                return;
    627721        }
    628722
     723        fibril_mutex_unlock(&socket->lock);
    629724        async_answer_0(callid, EOK);
    630725}
     
    640735        log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
    641736        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);
    642764}
    643765
  • uspace/srv/net/tl/tcp/tcp_type.h

    r827ec41 rae481e0  
    152152} acpass_t;
    153153
    154 typedef struct tcp_conn {
     154typedef enum {
     155        tcp_open_nonblock = 1
     156} tcp_open_flags_t;
     157
     158typedef struct tcp_conn tcp_conn_t;
     159
     160/** Connection state change callback function */
     161typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
     162
     163/** Connection */
     164struct tcp_conn {
    155165        char *name;
    156166        link_t link;
     167
     168        /** Connection state change callback function */
     169        tcp_cstate_cb_t cstate_cb;
     170        /** Argument to @c cstate_cb */
     171        void *cstate_cb_arg;
    157172
    158173        /** Connection identification (local and foreign socket) */
     
    233248        /** Initial receive sequence number */
    234249        uint32_t irs;
    235 } tcp_conn_t;
    236 
    237 typedef struct {
    238         unsigned dummy;
     250};
     251
     252/** Data returned by Status user call */
     253typedef struct {
     254        /** Connection state */
     255        tcp_cstate_t cstate;
    239256} tcp_conn_status_t;
    240257
     
    314331} tcp_client_t;
    315332
    316 typedef struct {
     333typedef struct tcp_sockdata {
     334        /** Lock */
     335        fibril_mutex_t lock;
     336        /** Socket core */
     337        socket_core_t *sock_core;
    317338        /** Client */
    318339        tcp_client_t *client;
     
    321342        /** Local address */
    322343        netaddr_t laddr;
     344        /** Backlog size */
     345        int backlog;
     346        /** Array of listening connections, @c backlog elements */
     347        struct tcp_sock_lconn **lconn;
     348        /** List of connections (from lconn) that are ready to be accepted */
     349        list_t ready;
    323350} tcp_sockdata_t;
     351
     352typedef struct tcp_sock_lconn {
     353        tcp_conn_t *conn;
     354        tcp_sockdata_t *socket;
     355        int index;
     356        link_t ready_list;
     357} tcp_sock_lconn_t;
     358
    324359
    325360#endif
  • uspace/srv/net/tl/tcp/test.c

    r827ec41 rae481e0  
    6262        fsock.addr.ipv4 = 0x7f000001;
    6363        printf("S: User open...\n");
    64         tcp_uc_open(&lsock, &fsock, ap_passive, &conn);
     64        tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
    6565        conn->name = (char *) "S";
    6666
     
    102102        async_usleep(1000*1000*3);
    103103        printf("C: User open...\n");
    104         tcp_uc_open(&lsock, &fsock, ap_active, &conn);
     104        tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
    105105        conn->name = (char *) "C";
    106106
  • uspace/srv/net/tl/tcp/ucall.c

    r827ec41 rae481e0  
    5353 * @param fsock         Foreign socket
    5454 * @param acpass        Active/passive
     55 * @param oflags        Open flags
    5556 * @param conn          Connection
    5657 *
     
    6566 */
    6667tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
    67     tcp_conn_t **conn)
     68    tcp_open_flags_t oflags, tcp_conn_t **conn)
    6869{
    6970        tcp_conn_t *nconn;
    7071
    71         log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %p)",
     72        log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
    7273            lsock, fsock, acpass == ap_active ? "active" : "passive",
    73             conn);
     74            oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
    7475
    7576        nconn = tcp_conn_new(lsock, fsock);
     
    7980                /* Synchronize (initiate) connection */
    8081                tcp_conn_sync(nconn);
     82        }
     83
     84        if (oflags == tcp_open_nonblock) {
     85                *conn = nconn;
     86                return TCP_EOK;
    8187        }
    8288
     
    101107
    102108        *conn = nconn;
     109        log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
    103110        return TCP_EOK;
    104111}
     
    258265{
    259266        log_msg(LVL_DEBUG, "tcp_uc_status()");
     267        cstatus->cstate = conn->cstate;
    260268}
    261269
     
    270278        log_msg(LVL_DEBUG, "tcp_uc_delete()");
    271279        tcp_conn_delete(conn);
     280}
     281
     282void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
     283{
     284        log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
     285            conn, cb, arg);
     286
     287        conn->cstate_cb = cb;
     288        conn->cstate_cb_arg = arg;
    272289}
    273290
  • uspace/srv/net/tl/tcp/ucall.h

    r827ec41 rae481e0  
    4242 * User calls
    4343 */
    44 extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t, tcp_conn_t **);
     44extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t,
     45    tcp_open_flags_t, tcp_conn_t **);
    4546extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
    4647extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
     
    4950extern void tcp_uc_status(tcp_conn_t *, tcp_conn_status_t *);
    5051extern void tcp_uc_delete(tcp_conn_t *);
     52extern void tcp_uc_set_cstate_cb(tcp_conn_t *, tcp_cstate_cb_t, void *);
    5153
    5254/*
Note: See TracChangeset for help on using the changeset viewer.