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


Ignore:
Timestamp:
2015-06-17T23:45:24Z (9 years ago)
Author:
Michal Koutný <xm.koutny+hos@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
523b17a
Parents:
fc7bf19 (diff), 2654afb (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:

Sync with mainline

File:
1 edited

Legend:

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

    rfc7bf19 rcf3aee19  
    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;
     
    10061011
    10071012        /* Signal to the receive function that new data has arrived */
    1008         fibril_condvar_broadcast(&conn->rcv_buf_cv);
     1013        if (xfer_size > 0) {
     1014                fibril_condvar_broadcast(&conn->rcv_buf_cv);
     1015                if (conn->cb != NULL && conn->cb->recv_data != NULL)
     1016                        conn->cb->recv_data(conn, conn->cb_arg);
     1017        }
    10091018
    10101019        log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
     
    10981107                conn->rcv_buf_fin = true;
    10991108                fibril_condvar_broadcast(&conn->rcv_buf_cv);
     1109                if (conn->cb != NULL && conn->cb->recv_data != NULL)
     1110                        conn->cb->recv_data(conn, conn->cb_arg);
    11001111
    11011112                tcp_segment_delete(seg);
     
    11681179 *
    11691180 * @param conn          Connection
    1170  * @param seg           Segment
    1171  */
    1172 void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
    1173 {
     1181 * @param epp           Endpoint pair on which segment was received
     1182 * @param seg           Segment
     1183 */
     1184void tcp_conn_segment_arrived(tcp_conn_t *conn, inet_ep2_t *epp,
     1185    tcp_segment_t *seg)
     1186{
     1187        inet_ep2_t aepp;
     1188        inet_ep2_t oldepp;
     1189        int rc;
     1190
    11741191        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)",
    11751192            conn->name, seg);
    11761193
     1194        tcp_conn_lock(conn);
     1195
     1196        if (conn->cstate == st_closed) {
     1197                log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
     1198                tcp_unexpected_segment(epp, seg);
     1199                tcp_conn_unlock(conn);
     1200                return;
     1201        }
     1202
     1203        if (inet_addr_is_any(&conn->ident.remote.addr) ||
     1204            conn->ident.remote.port == inet_port_any ||
     1205            inet_addr_is_any(&conn->ident.local.addr)) {
     1206
     1207                log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_segment_arrived: "
     1208                    "Changing connection ID, updating amap.");
     1209                oldepp = conn->ident;
     1210
     1211                /* Need to remove and re-insert connection with new identity */
     1212                fibril_mutex_lock(&conn_list_lock);
     1213
     1214                if (inet_addr_is_any(&conn->ident.remote.addr))
     1215                        conn->ident.remote.addr = epp->remote.addr;
     1216
     1217                if (conn->ident.remote.port == inet_port_any)
     1218                        conn->ident.remote.port = epp->remote.port;
     1219
     1220                if (inet_addr_is_any(&conn->ident.local.addr))
     1221                        conn->ident.local.addr = epp->local.addr;
     1222
     1223                rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp);
     1224                if (rc != EOK) {
     1225                        assert(rc != EEXISTS);
     1226                        assert(rc == ENOMEM);
     1227                        log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
     1228                        fibril_mutex_unlock(&conn_list_lock);
     1229                        tcp_conn_unlock(conn);
     1230                        return;
     1231                }
     1232
     1233                amap_remove(amap, &oldepp);
     1234                fibril_mutex_unlock(&conn_list_lock);
     1235
     1236                conn->name = (char *) "a";
     1237        }
     1238
    11771239        switch (conn->cstate) {
    11781240        case st_listen:
    1179                 tcp_conn_sa_listen(conn, seg); break;
     1241                tcp_conn_sa_listen(conn, seg);
     1242                break;
    11801243        case st_syn_sent:
    1181                 tcp_conn_sa_syn_sent(conn, seg); break;
     1244                tcp_conn_sa_syn_sent(conn, seg);
     1245                break;
    11821246        case st_syn_received:
    11831247        case st_established:
     
    11891253        case st_time_wait:
    11901254                /* Process segments in order of sequence number */
    1191                 tcp_conn_sa_queue(conn, seg); break;
     1255                tcp_conn_sa_queue(conn, seg);
     1256                break;
    11921257        case st_closed:
    11931258                log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate);
    11941259                assert(false);
    11951260        }
     1261
     1262        tcp_conn_unlock(conn);
    11961263}
    11971264
     
    12161283
    12171284        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
    1218         tcp_conn_remove(conn);
    12191285        tcp_conn_state_set(conn, st_closed);
    12201286
     
    12631329}
    12641330
    1265 /** Handle unexpected segment received on a socket pair.
     1331/** Handle unexpected segment received on an endpoint pair.
    12661332 *
    12671333 * We reply with an RST unless the received segment has RST.
    12681334 *
    1269  * @param sp            Socket pair which received the segment
     1335 * @param sp            Endpoint pair which received the segment
    12701336 * @param seg           Unexpected segment
    12711337 */
    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);
     1338void tcp_unexpected_segment(inet_ep2_t *epp, tcp_segment_t *seg)
     1339{
     1340        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", epp,
     1341            seg);
    12751342
    12761343        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;
     1344                tcp_reply_rst(epp, seg);
     1345}
     1346
     1347/** Compute flipped endpoint pair for response.
     1348 *
     1349 * Flipped endpoint pair has local and remote endpoints exchanged.
     1350 *
     1351 * @param epp           Endpoint pair
     1352 * @param fepp          Place to store flipped endpoint pair
     1353 */
     1354void tcp_ep2_flipped(inet_ep2_t *epp, inet_ep2_t *fepp)
     1355{
     1356        fepp->local = epp->remote;
     1357        fepp->remote = epp->local;
    12911358}
    12921359
    12931360/** Send RST in response to an incoming segment.
    12941361 *
    1295  * @param sp            Socket pair which received the segment
     1362 * @param epp           Endpoint pair which received the segment
    12961363 * @param seg           Incoming segment
    12971364 */
    1298 void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
     1365void tcp_reply_rst(inet_ep2_t *epp, tcp_segment_t *seg)
    12991366{
    13001367        tcp_segment_t *rseg;
    13011368
    1302         log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
     1369        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", epp, seg);
    13031370
    13041371        rseg = tcp_segment_make_rst(seg);
    1305         tcp_transmit_segment(sp, rseg);
     1372        tcp_transmit_segment(epp, rseg);
    13061373}
    13071374
Note: See TracChangeset for help on using the changeset viewer.