Changeset 153cc76a in mainline for uspace/srv/net/tl/tcp/conn.c


Ignore:
Timestamp:
2011-12-23T16:42:22Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7e1b130
Parents:
4291215 (diff), 2f0dd2a (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:

Mainline changes.

File:
1 edited

Legend:

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

    r4291215 r153cc76a  
    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);
    117122
    118123        conn->cstate = st_listen;
    119124        conn->reset = false;
     125        conn->deleted = false;
    120126        conn->ap = ap_passive;
    121127        conn->fin_is_acked = false;
     
    141147}
    142148
     149/** Destroy connection structure.
     150 *
     151 * Connection structure should be destroyed when the folowing condtitions
     152 * are met:
     153 * (1) user has deleted the connection
     154 * (2) the connection has entered closed state
     155 * (3) nobody is holding references to the connection
     156 *
     157 * This happens when @a conn->refcnt is zero as we count (1) and (2)
     158 * as special references.
     159 *
     160 * @param conn          Connection
     161 */
     162static void tcp_conn_free(tcp_conn_t *conn)
     163{
     164        log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
     165        tcp_tqueue_fini(&conn->retransmit);
     166
     167        if (conn->rcv_buf != NULL)
     168                free(conn->rcv_buf);
     169        if (conn->snd_buf != NULL)
     170                free(conn->snd_buf);
     171        if (conn->tw_timer != NULL)
     172                fibril_timer_destroy(conn->tw_timer);
     173        free(conn);
     174}
     175
     176/** Add reference to connection.
     177 *
     178 * Increase connection reference count by one.
     179 *
     180 * @param conn          Connection
     181 */
     182void tcp_conn_addref(tcp_conn_t *conn)
     183{
     184        log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
     185        atomic_inc(&conn->refcnt);
     186}
     187
     188/** Remove reference from connection.
     189 *
     190 * Decrease connection reference count by one.
     191 *
     192 * @param conn          Connection
     193 */
     194void tcp_conn_delref(tcp_conn_t *conn)
     195{
     196        log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
     197
     198        if (atomic_predec(&conn->refcnt) == 0)
     199                tcp_conn_free(conn);
     200}
     201
     202/** Delete connection.
     203 *
     204 * The caller promises not make no further references to @a conn.
     205 * TCP will free @a conn eventually.
     206 *
     207 * @param conn          Connection
     208 */
     209void tcp_conn_delete(tcp_conn_t *conn)
     210{
     211        log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
     212
     213        assert(conn->deleted == false);
     214        tcp_conn_delref(conn);
     215}
     216
    143217/** Enlist connection.
    144218 *
     
    147221void tcp_conn_add(tcp_conn_t *conn)
    148222{
     223        tcp_conn_addref(conn);
     224        fibril_mutex_lock(&conn_list_lock);
    149225        list_append(&conn->link, &conn_list);
     226        fibril_mutex_unlock(&conn_list_lock);
    150227}
    151228
     
    156233void tcp_conn_remove(tcp_conn_t *conn)
    157234{
     235        fibril_mutex_lock(&conn_list_lock);
    158236        list_remove(&conn->link);
     237        fibril_mutex_unlock(&conn_list_lock);
     238        tcp_conn_delref(conn);
    159239}
    160240
    161241static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
    162242{
    163         fibril_mutex_lock(&conn->cstate_lock);
     243        tcp_cstate_t old_state;
     244
     245        old_state = conn->cstate;
    164246        conn->cstate = nstate;
    165247        fibril_condvar_broadcast(&conn->cstate_cv);
    166         fibril_mutex_unlock(&conn->cstate_lock);
     248
     249        assert(old_state != st_closed);
     250        if (nstate == st_closed) {
     251                /* Drop one reference for now being in closed state */
     252                tcp_conn_delref(conn);
     253        }
    167254}
    168255
     
    251338 * A connection is uniquely identified by a socket pair. Look up our
    252339 * connection map and return connection structure based on socket pair.
     340 * The connection reference count is bumped by one.
    253341 *
    254342 * @param sp    Socket pair
    255343 * @return      Connection structure or NULL if not found.
    256344 */
    257 tcp_conn_t *tcp_conn_find(tcp_sockpair_t *sp)
     345tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
    258346{
    259347        log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp);
     348
     349        fibril_mutex_lock(&conn_list_lock);
    260350
    261351        list_foreach(conn_list, link) {
     
    266356                    csp->local.addr.ipv4, csp->local.port);
    267357                if (tcp_sockpair_match(sp, csp)) {
     358                        tcp_conn_addref(conn);
     359                        fibril_mutex_unlock(&conn_list_lock);
    268360                        return conn;
    269361                }
    270362        }
    271363
     364        fibril_mutex_unlock(&conn_list_lock);
    272365        return NULL;
    273366}
     
    287380
    288381        fibril_condvar_broadcast(&conn->rcv_buf_cv);
     382        fibril_condvar_broadcast(&conn->snd_buf_cv);
    289383}
    290384
     
    397491                    conn->snd_una, seg->ack, conn->snd_nxt);
    398492                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);
     493                        if ((seg->ctrl & CTL_RST) == 0) {
     494                                log_msg(LVL_WARN, "ACK not acceptable, send RST");
     495                                tcp_reply_rst(&conn->ident, seg);
     496                        } else {
     497                                log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
     498                        }
    401499                        return;
    402500                }
     
    404502
    405503        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;
     504                /* If we get here, we have either an acceptable ACK or no ACK */
     505                if ((seg->ctrl & CTL_ACK) != 0) {
     506                        log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
     507                            conn->name);
     508                        /* Reset connection */
     509                        tcp_conn_reset(conn);
     510                        return;
     511                } else {
     512                        log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
     513                            conn->name);
     514                        return;
     515                }
    412516        }
    413517
     
    858962        tcp_conn_trim_seg_to_wnd(conn, seg);
    859963
    860         fibril_mutex_lock(&conn->rcv_buf_lock);
    861 
    862964        /* Determine how many bytes to copy */
    863965        text_size = tcp_segment_text_size(seg);
     
    871973        /* Signal to the receive function that new data has arrived */
    872974        fibril_condvar_broadcast(&conn->rcv_buf_cv);
    873         fibril_mutex_unlock(&conn->rcv_buf_lock);
    874975
    875976        log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
     
    9611062
    9621063                /* Add FIN to the receive buffer */
    963                 fibril_mutex_lock(&conn->rcv_buf_lock);
    9641064                conn->rcv_buf_fin = true;
    9651065                fibril_condvar_broadcast(&conn->rcv_buf_cv);
    966                 fibril_mutex_unlock(&conn->rcv_buf_lock);
    9671066
    9681067                tcp_segment_delete(seg);
     
    10731172        log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
    10741173
     1174        fibril_mutex_lock(&conn->lock);
     1175
    10751176        if (conn->cstate == st_closed) {
    10761177                log_msg(LVL_DEBUG, "Connection already closed.");
     1178                fibril_mutex_unlock(&conn->lock);
     1179                tcp_conn_delref(conn);
    10771180                return;
    10781181        }
     
    10811184        tcp_conn_remove(conn);
    10821185        tcp_conn_state_set(conn, st_closed);
     1186
     1187        fibril_mutex_unlock(&conn->lock);
     1188        tcp_conn_delref(conn);
    10831189}
    10841190
     
    10891195void tcp_conn_tw_timer_set(tcp_conn_t *conn)
    10901196{
     1197        tcp_conn_addref(conn);
    10911198        fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
    10921199            (void *)conn);
     
    10991206void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
    11001207{
    1101         fibril_timer_clear(conn->tw_timer);
     1208        if (fibril_timer_clear(conn->tw_timer) == fts_active)
     1209                tcp_conn_delref(conn);
    11021210}
    11031211
Note: See TracChangeset for help on using the changeset viewer.