Changeset 048cd69 in mainline for uspace/srv/net/tcp/conn.c


Ignore:
Timestamp:
2015-06-07T15:41:04Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
204ba47
Parents:
4d11204 (diff), c3f7d37 (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 network transport layer API rewrite.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tcp/conn.c

    r4d11204 r048cd69  
    11/*
    2  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2015 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3636
    3737#include <adt/list.h>
    38 #include <stdbool.h>
    3938#include <errno.h>
     39#include <inet/endpoint.h>
    4040#include <io/log.h>
    4141#include <macros.h>
     42#include <nettl/amap.h>
     43#include <stdbool.h>
    4244#include <stdlib.h>
    4345#include "conn.h"
     
    5557#define TIME_WAIT_TIMEOUT       (2*MAX_SEGMENT_LIFETIME)
    5658
    57 LIST_INITIALIZE(conn_list);
    58 FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
     59static LIST_INITIALIZE(conn_list);
     60/** Taken after tcp_conn_t lock */
     61static FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
     62static amap_t *amap;
    5963
    6064static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
     
    6266static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
    6367
     68/** Initialize connections. */
     69int tcp_conns_init(void)
     70{
     71        int rc;
     72
     73        rc = amap_create(&amap);
     74        if (rc != EOK) {
     75                assert(rc == ENOMEM);
     76                return ENOMEM;
     77        }
     78
     79        return EOK;
     80}
     81
    6482/** Create new connection structure.
    6583 *
    66  * @param lsock         Local socket (will be deeply copied)
    67  * @param fsock         Foreign socket (will be deeply copied)
     84 * @param epp           Endpoint pair (will be deeply copied)
    6885 * @return              New connection or NULL
    6986 */
    70 tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
     87tcp_conn_t *tcp_conn_new(inet_ep2_t *epp)
    7188{
    7289        tcp_conn_t *conn = NULL;
     
    121138        fibril_condvar_initialize(&conn->cstate_cv);
    122139
    123         conn->cstate_cb = NULL;
     140        conn->cb = NULL;
    124141
    125142        conn->cstate = st_listen;
     
    128145        conn->ap = ap_passive;
    129146        conn->fin_is_acked = false;
    130         conn->ident.local = *lsock;
    131         if (fsock != NULL)
    132                 conn->ident.foreign = *fsock;
     147        if (epp != NULL)
     148                conn->ident = *epp;
    133149
    134150        return conn;
     
    184200void tcp_conn_addref(tcp_conn_t *conn)
    185201{
    186         log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn);
     202        log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p) before=%zu",
     203            conn->name, conn, atomic_get(&conn->refcnt));
    187204        atomic_inc(&conn->refcnt);
    188205}
     
    196213void tcp_conn_delref(tcp_conn_t *conn)
    197214{
    198         log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn);
     215        log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p) before=%zu",
     216            conn->name, conn, atomic_get(&conn->refcnt));
    199217
    200218        if (atomic_predec(&conn->refcnt) == 0)
     
    237255
    238256        assert(conn->deleted == false);
     257        conn->deleted = true;
     258        conn->cb = NULL;
     259        conn->cb_arg = NULL;
    239260        tcp_conn_delref(conn);
    240261}
     
    244265 * Add connection to the connection map.
    245266 */
    246 void tcp_conn_add(tcp_conn_t *conn)
    247 {
     267int tcp_conn_add(tcp_conn_t *conn)
     268{
     269        inet_ep2_t aepp;
     270        int rc;
     271
    248272        tcp_conn_addref(conn);
    249273        fibril_mutex_lock(&conn_list_lock);
     274
     275        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_add: conn=%p", conn);
     276
     277        rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp);
     278        if (rc != EOK) {
     279                tcp_conn_delref(conn);
     280                fibril_mutex_unlock(&conn_list_lock);
     281                return rc;
     282        }
     283
     284        conn->ident = aepp;
    250285        list_append(&conn->link, &conn_list);
    251286        fibril_mutex_unlock(&conn_list_lock);
     287
     288        return EOK;
    252289}
    253290
     
    259296{
    260297        fibril_mutex_lock(&conn_list_lock);
     298        amap_remove(amap, &conn->ident);
    261299        list_remove(&conn->link);
    262300        fibril_mutex_unlock(&conn_list_lock);
     
    275313
    276314        /* Run user callback function */
    277         if (conn->cstate_cb != NULL) {
     315        if (conn->cb != NULL && conn->cb->cstate_change != NULL) {
    278316                log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - run user CB");
    279                 conn->cstate_cb(conn, conn->cstate_cb_arg);
     317                conn->cb->cstate_change(conn, conn->cb_arg, old_state);
    280318        } else {
    281319                log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - no user CB");
     
    284322        assert(old_state != st_closed);
    285323        if (nstate == st_closed) {
     324                tcp_conn_remove(conn);
    286325                /* Drop one reference for now being in closed state */
    287326                tcp_conn_delref(conn);
     
    332371}
    333372
    334 /** Match socket with pattern. */
    335 static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
    336 {
    337         log_msg(LOG_DEFAULT, LVL_DEBUG2,
    338             "tcp_socket_match(sock=(%u), pat=(%u))", sock->port, patt->port);
    339        
    340         if ((!inet_addr_is_any(&patt->addr)) &&
    341             (!inet_addr_compare(&patt->addr, &sock->addr)))
    342                 return false;
    343 
    344         if ((patt->port != TCP_PORT_ANY) &&
    345             (patt->port != sock->port))
    346                 return false;
    347 
    348         log_msg(LOG_DEFAULT, LVL_DEBUG2, " -> match");
    349 
    350         return true;
    351 }
    352 
    353 /** Match socket pair with pattern. */
    354 static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
    355 {
    356         log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_sockpair_match(%p, %p)", sp, pattern);
    357 
    358         if (!tcp_socket_match(&sp->local, &pattern->local))
    359                 return false;
    360 
    361         if (!tcp_socket_match(&sp->foreign, &pattern->foreign))
    362                 return false;
    363 
    364         return true;
    365 }
    366 
    367 /** Find connection structure for specified socket pair.
    368  *
    369  * A connection is uniquely identified by a socket pair. Look up our
    370  * connection map and return connection structure based on socket pair.
     373/** Find connection structure for specified endpoint pair.
     374 *
     375 * A connection is uniquely identified by a endpoint pair. Look up our
     376 * connection map and return connection structure based on endpoint pair.
    371377 * The connection reference count is bumped by one.
    372378 *
    373  * @param sp    Socket pair
     379 * @param epp   Endpoint pair
    374380 * @return      Connection structure or NULL if not found.
    375381 */
    376 tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
    377 {
    378         log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
    379        
    380         log_msg(LOG_DEFAULT, LVL_DEBUG2, "compare conn (f:(%u), l:(%u))",
    381             sp->foreign.port, sp->local.port);
    382        
     382tcp_conn_t *tcp_conn_find_ref(inet_ep2_t *epp)
     383{
     384        int rc;
     385        void *arg;
     386        tcp_conn_t *conn;
     387
     388        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", epp);
     389
    383390        fibril_mutex_lock(&conn_list_lock);
    384        
    385         list_foreach(conn_list, link, tcp_conn_t, conn) {
    386                 tcp_sockpair_t *csp = &conn->ident;
    387                
    388                 log_msg(LOG_DEFAULT, LVL_DEBUG2, " - with (f:(%u), l:(%u))",
    389                     csp->foreign.port, csp->local.port);
    390                
    391                 if (tcp_sockpair_match(sp, csp)) {
    392                         tcp_conn_addref(conn);
    393                         fibril_mutex_unlock(&conn_list_lock);
    394                         return conn;
    395                 }
    396         }
    397        
     391
     392        rc = amap_find_match(amap, epp, &arg);
     393        if (rc != EOK) {
     394                assert(rc == ENOENT);
     395                fibril_mutex_unlock(&conn_list_lock);
     396                return NULL;
     397        }
     398
     399        conn = (tcp_conn_t *)arg;
     400        tcp_conn_addref(conn);
     401
    398402        fibril_mutex_unlock(&conn_list_lock);
    399         return NULL;
     403        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref: got conn=%p",
     404            conn);
     405        return conn;
    400406}
    401407
     
    407413{
    408414        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
     415        conn->reset = true;
    409416        tcp_conn_state_set(conn, st_closed);
    410         conn->reset = true;
    411417
    412418        tcp_conn_tw_timer_clear(conn);
     
    877883        if (conn->fin_is_acked) {
    878884                log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
    879                 tcp_conn_remove(conn);
    880885                tcp_conn_state_set(conn, st_closed);
    881886                return cp_done;
     
    10071012        /* Signal to the receive function that new data has arrived */
    10081013        fibril_condvar_broadcast(&conn->rcv_buf_cv);
     1014        if (conn->cb != NULL && conn->cb->recv_data != NULL)
     1015                conn->cb->recv_data(conn, conn->cb_arg);
    10091016
    10101017        log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
     
    10981105                conn->rcv_buf_fin = true;
    10991106                fibril_condvar_broadcast(&conn->rcv_buf_cv);
     1107                if (conn->cb != NULL && conn->cb->recv_data != NULL)
     1108                        conn->cb->recv_data(conn, conn->cb_arg);
    11001109
    11011110                tcp_segment_delete(seg);
     
    11681177 *
    11691178 * @param conn          Connection
    1170  * @param seg           Segment
    1171  */
    1172 void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
    1173 {
     1179 * @param epp           Endpoint pair on which segment was received
     1180 * @param seg           Segment
     1181 */
     1182void tcp_conn_segment_arrived(tcp_conn_t *conn, inet_ep2_t *epp,
     1183    tcp_segment_t *seg)
     1184{
     1185        inet_ep2_t aepp;
     1186        inet_ep2_t oldepp;
     1187        int rc;
     1188
    11741189        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)",
    11751190            conn->name, seg);
    11761191
     1192        tcp_conn_lock(conn);
     1193
     1194        if (conn->cstate == st_closed) {
     1195                log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
     1196                tcp_unexpected_segment(epp, seg);
     1197                tcp_conn_unlock(conn);
     1198                return;
     1199        }
     1200
     1201        if (inet_addr_is_any(&conn->ident.remote.addr) ||
     1202            conn->ident.remote.port == inet_port_any ||
     1203            inet_addr_is_any(&conn->ident.local.addr)) {
     1204
     1205                log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_segment_arrived: "
     1206                    "Changing connection ID, updating amap.");
     1207                oldepp = conn->ident;
     1208
     1209                /* Need to remove and re-insert connection with new identity */
     1210                fibril_mutex_lock(&conn_list_lock);
     1211
     1212                if (inet_addr_is_any(&conn->ident.remote.addr))
     1213                        conn->ident.remote.addr = epp->remote.addr;
     1214
     1215                if (conn->ident.remote.port == inet_port_any)
     1216                        conn->ident.remote.port = epp->remote.port;
     1217
     1218                if (inet_addr_is_any(&conn->ident.local.addr))
     1219                        conn->ident.local.addr = epp->local.addr;
     1220
     1221                rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp);
     1222                if (rc != EOK) {
     1223                        assert(rc != EEXISTS);
     1224                        assert(rc == ENOMEM);
     1225                        log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
     1226                        fibril_mutex_unlock(&conn_list_lock);
     1227                        tcp_conn_unlock(conn);
     1228                        return;
     1229                }
     1230
     1231                amap_remove(amap, &oldepp);
     1232                fibril_mutex_unlock(&conn_list_lock);
     1233
     1234                conn->name = (char *) "a";
     1235        }
     1236
    11771237        switch (conn->cstate) {
    11781238        case st_listen:
    1179                 tcp_conn_sa_listen(conn, seg); break;
     1239                tcp_conn_sa_listen(conn, seg);
     1240                break;
    11801241        case st_syn_sent:
    1181                 tcp_conn_sa_syn_sent(conn, seg); break;
     1242                tcp_conn_sa_syn_sent(conn, seg);
     1243                break;
    11821244        case st_syn_received:
    11831245        case st_established:
     
    11891251        case st_time_wait:
    11901252                /* Process segments in order of sequence number */
    1191                 tcp_conn_sa_queue(conn, seg); break;
     1253                tcp_conn_sa_queue(conn, seg);
     1254                break;
    11921255        case st_closed:
    11931256                log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate);
    11941257                assert(false);
    11951258        }
     1259
     1260        tcp_conn_unlock(conn);
    11961261}
    11971262
     
    12161281
    12171282        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
    1218         tcp_conn_remove(conn);
    12191283        tcp_conn_state_set(conn, st_closed);
    12201284
     
    12631327}
    12641328
    1265 /** Handle unexpected segment received on a socket pair.
     1329/** Handle unexpected segment received on an endpoint pair.
    12661330 *
    12671331 * We reply with an RST unless the received segment has RST.
    12681332 *
    1269  * @param sp            Socket pair which received the segment
     1333 * @param sp            Endpoint pair which received the segment
    12701334 * @param seg           Unexpected segment
    12711335 */
    1272 void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
    1273 {
    1274         log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
     1336void tcp_unexpected_segment(inet_ep2_t *epp, tcp_segment_t *seg)
     1337{
     1338        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", epp,
     1339            seg);
    12751340
    12761341        if ((seg->ctrl & CTL_RST) == 0)
    1277                 tcp_reply_rst(sp, seg);
    1278 }
    1279 
    1280 /** Compute flipped socket pair for response.
    1281  *
    1282  * Flipped socket pair has local and foreign sockets exchanged.
    1283  *
    1284  * @param sp            Socket pair
    1285  * @param fsp           Place to store flipped socket pair
    1286  */
    1287 void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)
    1288 {
    1289         fsp->local = sp->foreign;
    1290         fsp->foreign = sp->local;
     1342                tcp_reply_rst(epp, seg);
     1343}
     1344
     1345/** Compute flipped endpoint pair for response.
     1346 *
     1347 * Flipped endpoint pair has local and remote endpoints exchanged.
     1348 *
     1349 * @param epp           Endpoint pair
     1350 * @param fepp          Place to store flipped endpoint pair
     1351 */
     1352void tcp_ep2_flipped(inet_ep2_t *epp, inet_ep2_t *fepp)
     1353{
     1354        fepp->local = epp->remote;
     1355        fepp->remote = epp->local;
    12911356}
    12921357
    12931358/** Send RST in response to an incoming segment.
    12941359 *
    1295  * @param sp            Socket pair which received the segment
     1360 * @param epp           Endpoint pair which received the segment
    12961361 * @param seg           Incoming segment
    12971362 */
    1298 void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
     1363void tcp_reply_rst(inet_ep2_t *epp, tcp_segment_t *seg)
    12991364{
    13001365        tcp_segment_t *rseg;
    13011366
    1302         log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
     1367        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", epp, seg);
    13031368
    13041369        rseg = tcp_segment_make_rst(seg);
    1305         tcp_transmit_segment(sp, rseg);
     1370        tcp_transmit_segment(epp, rseg);
    13061371}
    13071372
Note: See TracChangeset for help on using the changeset viewer.