Changeset 7943c43 in mainline for uspace/srv/net/tl/tcp/conn.c


Ignore:
Timestamp:
2012-01-16T22:45:38Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
32817cc, 3fe58d3c
Parents:
9117ef9b (diff), 3ea725e (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 mainline changes.

File:
1 edited

Legend:

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

    r9117ef9b r7943c43  
    5656
    5757LIST_INITIALIZE(conn_list);
     58FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
    5859
    5960static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
     
    6162static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
    6263
    63 /** Create new segment structure.
     64/** Create new connection structure.
    6465 *
    6566 * @param lsock         Local socket (will be deeply copied)
    6667 * @param fsock         Foreign socket (will be deeply copied)
    67  * @return              New segment or NULL
     68 * @return              New connection or NULL
    6869 */
    6970tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
     
    8182                goto error;
    8283
     84        fibril_mutex_initialize(&conn->lock);
     85
     86        /* One for the user, one for not being in closed state */
     87        atomic_set(&conn->refcnt, 2);
     88
    8389        /* Allocate receive buffer */
    84         fibril_mutex_initialize(&conn->rcv_buf_lock);
    8590        fibril_condvar_initialize(&conn->rcv_buf_cv);
    8691        conn->rcv_buf_size = RCV_BUF_SIZE;
     
    9398
    9499        /** Allocate send buffer */
     100        fibril_condvar_initialize(&conn->snd_buf_cv);
    95101        conn->snd_buf_size = SND_BUF_SIZE;
    96102        conn->snd_buf_used = 0;
     
    113119
    114120        /* Connection state change signalling */
    115         fibril_mutex_initialize(&conn->cstate_lock);
    116121        fibril_condvar_initialize(&conn->cstate_cv);
     122
     123        conn->cstate_cb = NULL;
    117124
    118125        conn->cstate = st_listen;
    119126        conn->reset = false;
     127        conn->deleted = false;
    120128        conn->ap = ap_passive;
    121129        conn->fin_is_acked = false;
     
    141149}
    142150
     151/** Destroy connection structure.
     152 *
     153 * Connection structure should be destroyed when the folowing condtitions
     154 * are met:
     155 * (1) user has deleted the connection
     156 * (2) the connection has entered closed state
     157 * (3) nobody is holding references to the connection
     158 *
     159 * This happens when @a conn->refcnt is zero as we count (1) and (2)
     160 * as special references.
     161 *
     162 * @param conn          Connection
     163 */
     164static void tcp_conn_free(tcp_conn_t *conn)
     165{
     166        log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
     167        tcp_tqueue_fini(&conn->retransmit);
     168
     169        if (conn->rcv_buf != NULL)
     170                free(conn->rcv_buf);
     171        if (conn->snd_buf != NULL)
     172                free(conn->snd_buf);
     173        if (conn->tw_timer != NULL)
     174                fibril_timer_destroy(conn->tw_timer);
     175        free(conn);
     176}
     177
     178/** Add reference to connection.
     179 *
     180 * Increase connection reference count by one.
     181 *
     182 * @param conn          Connection
     183 */
     184void tcp_conn_addref(tcp_conn_t *conn)
     185{
     186        log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
     187        atomic_inc(&conn->refcnt);
     188}
     189
     190/** Remove reference from connection.
     191 *
     192 * Decrease connection reference count by one.
     193 *
     194 * @param conn          Connection
     195 */
     196void tcp_conn_delref(tcp_conn_t *conn)
     197{
     198        log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
     199
     200        if (atomic_predec(&conn->refcnt) == 0)
     201                tcp_conn_free(conn);
     202}
     203
     204/** Delete connection.
     205 *
     206 * The caller promises not make no further references to @a conn.
     207 * TCP will free @a conn eventually.
     208 *
     209 * @param conn          Connection
     210 */
     211void tcp_conn_delete(tcp_conn_t *conn)
     212{
     213        log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
     214
     215        assert(conn->deleted == false);
     216        tcp_conn_delref(conn);
     217}
     218
    143219/** Enlist connection.
    144220 *
     
    147223void tcp_conn_add(tcp_conn_t *conn)
    148224{
     225        tcp_conn_addref(conn);
     226        fibril_mutex_lock(&conn_list_lock);
    149227        list_append(&conn->link, &conn_list);
     228        fibril_mutex_unlock(&conn_list_lock);
    150229}
    151230
     
    156235void tcp_conn_remove(tcp_conn_t *conn)
    157236{
     237        fibril_mutex_lock(&conn_list_lock);
    158238        list_remove(&conn->link);
     239        fibril_mutex_unlock(&conn_list_lock);
     240        tcp_conn_delref(conn);
    159241}
    160242
    161243static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
    162244{
    163         fibril_mutex_lock(&conn->cstate_lock);
     245        tcp_cstate_t old_state;
     246
     247        log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
     248
     249        old_state = conn->cstate;
    164250        conn->cstate = nstate;
    165251        fibril_condvar_broadcast(&conn->cstate_cv);
    166         fibril_mutex_unlock(&conn->cstate_lock);
     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        }
     260
     261        assert(old_state != st_closed);
     262        if (nstate == st_closed) {
     263                /* Drop one reference for now being in closed state */
     264                tcp_conn_delref(conn);
     265        }
    167266}
    168267
     
    251350 * A connection is uniquely identified by a socket pair. Look up our
    252351 * connection map and return connection structure based on socket pair.
     352 * The connection reference count is bumped by one.
    253353 *
    254354 * @param sp    Socket pair
    255355 * @return      Connection structure or NULL if not found.
    256356 */
    257 tcp_conn_t *tcp_conn_find(tcp_sockpair_t *sp)
     357tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
    258358{
    259359        log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp);
     360
     361        fibril_mutex_lock(&conn_list_lock);
    260362
    261363        list_foreach(conn_list, link) {
     
    266368                    csp->local.addr.ipv4, csp->local.port);
    267369                if (tcp_sockpair_match(sp, csp)) {
     370                        tcp_conn_addref(conn);
     371                        fibril_mutex_unlock(&conn_list_lock);
    268372                        return conn;
    269373                }
    270374        }
    271375
     376        fibril_mutex_unlock(&conn_list_lock);
    272377        return NULL;
    273378}
     
    287392
    288393        fibril_condvar_broadcast(&conn->rcv_buf_cv);
     394        fibril_condvar_broadcast(&conn->snd_buf_cv);
    289395}
    290396
     
    397503                    conn->snd_una, seg->ack, conn->snd_nxt);
    398504                if (!seq_no_ack_acceptable(conn, seg->ack)) {
    399                         log_msg(LVL_WARN, "ACK not acceptable, send RST.");
    400                         tcp_reply_rst(&conn->ident, seg);
     505                        if ((seg->ctrl & CTL_RST) == 0) {
     506                                log_msg(LVL_WARN, "ACK not acceptable, send RST");
     507                                tcp_reply_rst(&conn->ident, seg);
     508                        } else {
     509                                log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
     510                        }
    401511                        return;
    402512                }
     
    404514
    405515        if ((seg->ctrl & CTL_RST) != 0) {
    406                 log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
    407                     conn->name);
    408                 /* Reset connection */
    409                 tcp_conn_reset(conn);
    410                 /* XXX delete connection */
    411                 return;
     516                /* If we get here, we have either an acceptable ACK or no ACK */
     517                if ((seg->ctrl & CTL_ACK) != 0) {
     518                        log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
     519                            conn->name);
     520                        /* Reset connection */
     521                        tcp_conn_reset(conn);
     522                        return;
     523                } else {
     524                        log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
     525                            conn->name);
     526                        return;
     527                }
    412528        }
    413529
     
    858974        tcp_conn_trim_seg_to_wnd(conn, seg);
    859975
    860         fibril_mutex_lock(&conn->rcv_buf_lock);
    861 
    862976        /* Determine how many bytes to copy */
    863977        text_size = tcp_segment_text_size(seg);
     
    871985        /* Signal to the receive function that new data has arrived */
    872986        fibril_condvar_broadcast(&conn->rcv_buf_cv);
    873         fibril_mutex_unlock(&conn->rcv_buf_lock);
    874987
    875988        log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
     
    9611074
    9621075                /* Add FIN to the receive buffer */
    963                 fibril_mutex_lock(&conn->rcv_buf_lock);
    9641076                conn->rcv_buf_fin = true;
    9651077                fibril_condvar_broadcast(&conn->rcv_buf_cv);
    966                 fibril_mutex_unlock(&conn->rcv_buf_lock);
    9671078
    9681079                tcp_segment_delete(seg);
     
    10731184        log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
    10741185
     1186        fibril_mutex_lock(&conn->lock);
     1187
    10751188        if (conn->cstate == st_closed) {
    10761189                log_msg(LVL_DEBUG, "Connection already closed.");
     1190                fibril_mutex_unlock(&conn->lock);
     1191                tcp_conn_delref(conn);
    10771192                return;
    10781193        }
     
    10811196        tcp_conn_remove(conn);
    10821197        tcp_conn_state_set(conn, st_closed);
     1198
     1199        fibril_mutex_unlock(&conn->lock);
     1200        tcp_conn_delref(conn);
    10831201}
    10841202
     
    10891207void tcp_conn_tw_timer_set(tcp_conn_t *conn)
    10901208{
     1209        tcp_conn_addref(conn);
    10911210        fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
    10921211            (void *)conn);
     
    10991218void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
    11001219{
    1101         fibril_timer_clear(conn->tw_timer);
     1220        if (fibril_timer_clear(conn->tw_timer) == fts_active)
     1221                tcp_conn_delref(conn);
    11021222}
    11031223
Note: See TracChangeset for help on using the changeset viewer.