Ignore:
File:
1 edited

Legend:

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

    rc3f7d37 r78192cc7  
    11/*
    2  * Copyright (c) 2015 Jiri Svoboda
     2 * Copyright (c) 2011 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3636
    3737#include <adt/list.h>
     38#include <stdbool.h>
    3839#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>
    4442#include <stdlib.h>
    4543#include "conn.h"
     
    5755#define TIME_WAIT_TIMEOUT       (2*MAX_SEGMENT_LIFETIME)
    5856
    59 static LIST_INITIALIZE(conn_list);
    60 /** Taken after tcp_conn_t lock */
    61 static FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
    62 static amap_t *amap;
     57LIST_INITIALIZE(conn_list);
     58FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
    6359
    6460static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
     
    6662static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
    6763
    68 /** Initialize connections. */
    69 int 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 
    8264/** Create new connection structure.
    8365 *
    84  * @param epp           Endpoint pair (will be deeply copied)
     66 * @param lsock         Local socket (will be deeply copied)
     67 * @param fsock         Foreign socket (will be deeply copied)
    8568 * @return              New connection or NULL
    8669 */
    87 tcp_conn_t *tcp_conn_new(inet_ep2_t *epp)
     70tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
    8871{
    8972        tcp_conn_t *conn = NULL;
     
    138121        fibril_condvar_initialize(&conn->cstate_cv);
    139122
    140         conn->cb = NULL;
     123        conn->cstate_cb = NULL;
    141124
    142125        conn->cstate = st_listen;
     
    145128        conn->ap = ap_passive;
    146129        conn->fin_is_acked = false;
    147         if (epp != NULL)
    148                 conn->ident = *epp;
     130        conn->ident.local = *lsock;
     131        if (fsock != NULL)
     132                conn->ident.foreign = *fsock;
    149133
    150134        return conn;
     
    200184void tcp_conn_addref(tcp_conn_t *conn)
    201185{
    202         log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p) before=%zu",
    203             conn->name, conn, atomic_get(&conn->refcnt));
     186        log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn);
    204187        atomic_inc(&conn->refcnt);
    205188}
     
    213196void tcp_conn_delref(tcp_conn_t *conn)
    214197{
    215         log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p) before=%zu",
    216             conn->name, conn, atomic_get(&conn->refcnt));
     198        log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn);
    217199
    218200        if (atomic_predec(&conn->refcnt) == 0)
     
    255237
    256238        assert(conn->deleted == false);
    257         conn->deleted = true;
    258         conn->cb = NULL;
    259         conn->cb_arg = NULL;
    260239        tcp_conn_delref(conn);
    261240}
     
    265244 * Add connection to the connection map.
    266245 */
    267 int tcp_conn_add(tcp_conn_t *conn)
    268 {
    269         inet_ep2_t aepp;
    270         int rc;
    271 
     246void tcp_conn_add(tcp_conn_t *conn)
     247{
    272248        tcp_conn_addref(conn);
    273249        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;
    285250        list_append(&conn->link, &conn_list);
    286251        fibril_mutex_unlock(&conn_list_lock);
    287 
    288         return EOK;
    289252}
    290253
     
    296259{
    297260        fibril_mutex_lock(&conn_list_lock);
    298         amap_remove(amap, &conn->ident);
    299261        list_remove(&conn->link);
    300262        fibril_mutex_unlock(&conn_list_lock);
     
    313275
    314276        /* Run user callback function */
    315         if (conn->cb != NULL && conn->cb->cstate_change != NULL) {
     277        if (conn->cstate_cb != NULL) {
    316278                log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - run user CB");
    317                 conn->cb->cstate_change(conn, conn->cb_arg, old_state);
     279                conn->cstate_cb(conn, conn->cstate_cb_arg);
    318280        } else {
    319281                log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - no user CB");
     
    322284        assert(old_state != st_closed);
    323285        if (nstate == st_closed) {
    324                 tcp_conn_remove(conn);
    325286                /* Drop one reference for now being in closed state */
    326287                tcp_conn_delref(conn);
     
    371332}
    372333
    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.
     334/** Match socket with pattern. */
     335static 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. */
     354static 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.
    377371 * The connection reference count is bumped by one.
    378372 *
    379  * @param epp   Endpoint pair
     373 * @param sp    Socket pair
    380374 * @return      Connection structure or NULL if not found.
    381375 */
    382 tcp_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 
     376tcp_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       
    390383        fibril_mutex_lock(&conn_list_lock);
    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 
     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       
    402398        fibril_mutex_unlock(&conn_list_lock);
    403         log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref: got conn=%p",
    404             conn);
    405         return conn;
     399        return NULL;
    406400}
    407401
     
    413407{
    414408        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
     409        tcp_conn_state_set(conn, st_closed);
    415410        conn->reset = true;
    416         tcp_conn_state_set(conn, st_closed);
    417411
    418412        tcp_conn_tw_timer_clear(conn);
     
    883877        if (conn->fin_is_acked) {
    884878                log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
     879                tcp_conn_remove(conn);
    885880                tcp_conn_state_set(conn, st_closed);
    886881                return cp_done;
     
    10121007        /* Signal to the receive function that new data has arrived */
    10131008        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);
    10161009
    10171010        log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
     
    11051098                conn->rcv_buf_fin = true;
    11061099                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);
    11091100
    11101101                tcp_segment_delete(seg);
     
    11771168 *
    11781169 * @param conn          Connection
    1179  * @param epp           Endpoint pair on which segment was received
    1180  * @param seg           Segment
    1181  */
    1182 void 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 
     1170 * @param seg           Segment
     1171 */
     1172void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
     1173{
    11891174        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)",
    11901175            conn->name, seg);
    11911176
    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 
    12371177        switch (conn->cstate) {
    12381178        case st_listen:
    1239                 tcp_conn_sa_listen(conn, seg);
    1240                 break;
     1179                tcp_conn_sa_listen(conn, seg); break;
    12411180        case st_syn_sent:
    1242                 tcp_conn_sa_syn_sent(conn, seg);
    1243                 break;
     1181                tcp_conn_sa_syn_sent(conn, seg); break;
    12441182        case st_syn_received:
    12451183        case st_established:
     
    12511189        case st_time_wait:
    12521190                /* Process segments in order of sequence number */
    1253                 tcp_conn_sa_queue(conn, seg);
    1254                 break;
     1191                tcp_conn_sa_queue(conn, seg); break;
    12551192        case st_closed:
    12561193                log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate);
    12571194                assert(false);
    12581195        }
    1259 
    1260         tcp_conn_unlock(conn);
    12611196}
    12621197
     
    12811216
    12821217        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
     1218        tcp_conn_remove(conn);
    12831219        tcp_conn_state_set(conn, st_closed);
    12841220
     
    13271263}
    13281264
    1329 /** Handle unexpected segment received on an endpoint pair.
     1265/** Handle unexpected segment received on a socket pair.
    13301266 *
    13311267 * We reply with an RST unless the received segment has RST.
    13321268 *
    1333  * @param sp            Endpoint pair which received the segment
     1269 * @param sp            Socket pair which received the segment
    13341270 * @param seg           Unexpected segment
    13351271 */
    1336 void 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);
     1272void 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);
    13401275
    13411276        if ((seg->ctrl & CTL_RST) == 0)
    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  */
    1352 void tcp_ep2_flipped(inet_ep2_t *epp, inet_ep2_t *fepp)
    1353 {
    1354         fepp->local = epp->remote;
    1355         fepp->remote = epp->local;
     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 */
     1287void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)
     1288{
     1289        fsp->local = sp->foreign;
     1290        fsp->foreign = sp->local;
    13561291}
    13571292
    13581293/** Send RST in response to an incoming segment.
    13591294 *
    1360  * @param epp           Endpoint pair which received the segment
     1295 * @param sp            Socket pair which received the segment
    13611296 * @param seg           Incoming segment
    13621297 */
    1363 void tcp_reply_rst(inet_ep2_t *epp, tcp_segment_t *seg)
     1298void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
    13641299{
    13651300        tcp_segment_t *rseg;
    13661301
    1367         log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", epp, seg);
     1302        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
    13681303
    13691304        rseg = tcp_segment_make_rst(seg);
    1370         tcp_transmit_segment(epp, rseg);
     1305        tcp_transmit_segment(sp, rseg);
    13711306}
    13721307
Note: See TracChangeset for help on using the changeset viewer.