/** Segment arrived */ void tcp_as_segment_arrived(tcp_sockpair_t *sp, tcp_segment_t *seg) { tcp_conn_t *conn; log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))", sp->foreign.addr.ipv4, sp->foreign.port, sp->local.addr.ipv4, sp->local.port); conn = tcp_conn_find_ref(sp); if (conn == NULL) { log_msg(LOG_DEFAULT, LVL_WARN, "No connection found."); tcp_unexpected_segment(sp, seg); return; } fibril_mutex_lock(&conn->lock); if (conn->cstate == st_closed) { log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed."); tcp_unexpected_segment(sp, seg); fibril_mutex_unlock(&conn->lock); tcp_conn_delref(conn); return; } if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY) conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4; if (conn->ident.foreign.port == TCP_PORT_ANY) conn->ident.foreign.port = sp->foreign.port; if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY) conn->ident.local.addr.ipv4 = sp->local.addr.ipv4; tcp_conn_segment_arrived(conn, seg); fibril_mutex_unlock(&conn->lock); tcp_conn_delref(conn); }
/** Segment arrived */ void tcp_as_segment_arrived(inet_ep2_t *epp, tcp_segment_t *seg) { tcp_conn_t *conn; log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_as_segment_arrived(f:(%u), l:(%u))", epp->remote.port, epp->local.port); conn = tcp_conn_find_ref(epp); if (conn == NULL) { log_msg(LOG_DEFAULT, LVL_WARN, "No connection found."); tcp_unexpected_segment(epp, seg); return; } tcp_conn_segment_arrived(conn, epp, seg); tcp_conn_delref(conn); }
/** Segment arrived on a connection. * * @param conn Connection * @param epp Endpoint pair on which segment was received * @param seg Segment */ void tcp_conn_segment_arrived(tcp_conn_t *conn, inet_ep2_t *epp, tcp_segment_t *seg) { inet_ep2_t aepp; inet_ep2_t oldepp; int rc; log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)", conn->name, seg); tcp_conn_lock(conn); if (conn->cstate == st_closed) { log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed."); tcp_unexpected_segment(epp, seg); tcp_conn_unlock(conn); return; } if (inet_addr_is_any(&conn->ident.remote.addr) || conn->ident.remote.port == inet_port_any || inet_addr_is_any(&conn->ident.local.addr)) { log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_segment_arrived: " "Changing connection ID, updating amap."); oldepp = conn->ident; /* Need to remove and re-insert connection with new identity */ fibril_mutex_lock(&conn_list_lock); if (inet_addr_is_any(&conn->ident.remote.addr)) conn->ident.remote.addr = epp->remote.addr; if (conn->ident.remote.port == inet_port_any) conn->ident.remote.port = epp->remote.port; if (inet_addr_is_any(&conn->ident.local.addr)) conn->ident.local.addr = epp->local.addr; rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp); if (rc != EOK) { assert(rc != EEXIST); assert(rc == ENOMEM); log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory."); fibril_mutex_unlock(&conn_list_lock); tcp_conn_unlock(conn); return; } amap_remove(amap, &oldepp); fibril_mutex_unlock(&conn_list_lock); conn->name = (char *) "a"; } switch (conn->cstate) { case st_listen: tcp_conn_sa_listen(conn, seg); break; case st_syn_sent: tcp_conn_sa_syn_sent(conn, seg); break; case st_syn_received: case st_established: case st_fin_wait_1: case st_fin_wait_2: case st_close_wait: case st_closing: case st_last_ack: case st_time_wait: /* Process segments in order of sequence number */ tcp_conn_sa_queue(conn, seg); break; case st_closed: log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate); assert(false); } tcp_conn_unlock(conn); }