Changes in / [a438de48:58f6229] in mainline
- Location:
- uspace
- Files:
-
- 8 edited
-
app/websrv/websrv.c (modified) (1 diff)
-
srv/net/tl/tcp/conn.c (modified) (18 diffs)
-
srv/net/tl/tcp/conn.h (modified) (2 diffs)
-
srv/net/tl/tcp/sock.c (modified) (1 diff)
-
srv/net/tl/tcp/tcp_type.h (modified) (3 diffs)
-
srv/net/tl/tcp/tqueue.c (modified) (8 diffs)
-
srv/net/tl/tcp/ucall.c (modified) (12 diffs)
-
srv/net/tl/tcp/ucall.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/websrv/websrv.c
ra438de48 r58f6229 304 304 if (rc != EOK) { 305 305 printf("Error closing connection socket: %d\n", rc); 306 closesocket(listen_sd);307 306 return 1; 308 307 } -
uspace/srv/net/tl/tcp/conn.c
ra438de48 r58f6229 56 56 57 57 LIST_INITIALIZE(conn_list); 58 FIBRIL_MUTEX_INITIALIZE(conn_list_lock);59 58 60 59 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg); … … 62 61 static void tcp_conn_tw_timer_clear(tcp_conn_t *conn); 63 62 64 /** Create new connectionstructure.63 /** Create new segment structure. 65 64 * 66 65 * @param lsock Local socket (will be deeply copied) 67 66 * @param fsock Foreign socket (will be deeply copied) 68 * @return New connectionor NULL67 * @return New segment or NULL 69 68 */ 70 69 tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock) … … 82 81 goto error; 83 82 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 89 83 /* Allocate receive buffer */ 84 fibril_mutex_initialize(&conn->rcv_buf_lock); 90 85 fibril_condvar_initialize(&conn->rcv_buf_cv); 91 86 conn->rcv_buf_size = RCV_BUF_SIZE; … … 98 93 99 94 /** Allocate send buffer */ 100 fibril_condvar_initialize(&conn->snd_buf_cv);101 95 conn->snd_buf_size = SND_BUF_SIZE; 102 96 conn->snd_buf_used = 0; … … 119 113 120 114 /* Connection state change signalling */ 115 fibril_mutex_initialize(&conn->cstate_lock); 121 116 fibril_condvar_initialize(&conn->cstate_cv); 122 117 123 118 conn->cstate = st_listen; 124 119 conn->reset = false; 125 conn->deleted = false;126 120 conn->ap = ap_passive; 127 121 conn->fin_is_acked = false; … … 147 141 } 148 142 149 /** Destroy connection structure.150 *151 * Connection structure should be destroyed when the folowing condtitions152 * are met:153 * (1) user has deleted the connection154 * (2) the connection has entered closed state155 * (3) nobody is holding references to the connection156 *157 * This happens when @a conn->refcnt is zero as we count (1) and (2)158 * as special references.159 *160 * @param conn Connection161 */162 static 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 Connection181 */182 void 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 Connection193 */194 void 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 Connection208 */209 void 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 217 143 /** Enlist connection. 218 144 * … … 221 147 void tcp_conn_add(tcp_conn_t *conn) 222 148 { 223 tcp_conn_addref(conn);224 fibril_mutex_lock(&conn_list_lock);225 149 list_append(&conn->link, &conn_list); 226 fibril_mutex_unlock(&conn_list_lock);227 150 } 228 151 … … 233 156 void tcp_conn_remove(tcp_conn_t *conn) 234 157 { 235 fibril_mutex_lock(&conn_list_lock);236 158 list_remove(&conn->link); 237 fibril_mutex_unlock(&conn_list_lock);238 tcp_conn_delref(conn);239 159 } 240 160 241 161 static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate) 242 162 { 243 tcp_cstate_t old_state; 244 245 old_state = conn->cstate; 163 fibril_mutex_lock(&conn->cstate_lock); 246 164 conn->cstate = nstate; 247 165 fibril_condvar_broadcast(&conn->cstate_cv); 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 } 166 fibril_mutex_unlock(&conn->cstate_lock); 254 167 } 255 168 … … 338 251 * A connection is uniquely identified by a socket pair. Look up our 339 252 * connection map and return connection structure based on socket pair. 340 * The connection reference count is bumped by one.341 253 * 342 254 * @param sp Socket pair 343 255 * @return Connection structure or NULL if not found. 344 256 */ 345 tcp_conn_t *tcp_conn_find _ref(tcp_sockpair_t *sp)257 tcp_conn_t *tcp_conn_find(tcp_sockpair_t *sp) 346 258 { 347 259 log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp); 348 349 fibril_mutex_lock(&conn_list_lock);350 260 351 261 list_foreach(conn_list, link) { … … 356 266 csp->local.addr.ipv4, csp->local.port); 357 267 if (tcp_sockpair_match(sp, csp)) { 358 tcp_conn_addref(conn);359 fibril_mutex_unlock(&conn_list_lock);360 268 return conn; 361 269 } 362 270 } 363 271 364 fibril_mutex_unlock(&conn_list_lock);365 272 return NULL; 366 273 } … … 380 287 381 288 fibril_condvar_broadcast(&conn->rcv_buf_cv); 382 fibril_condvar_broadcast(&conn->snd_buf_cv);383 289 } 384 290 … … 952 858 tcp_conn_trim_seg_to_wnd(conn, seg); 953 859 860 fibril_mutex_lock(&conn->rcv_buf_lock); 861 954 862 /* Determine how many bytes to copy */ 955 863 text_size = tcp_segment_text_size(seg); … … 963 871 /* Signal to the receive function that new data has arrived */ 964 872 fibril_condvar_broadcast(&conn->rcv_buf_cv); 873 fibril_mutex_unlock(&conn->rcv_buf_lock); 965 874 966 875 log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size); … … 1052 961 1053 962 /* Add FIN to the receive buffer */ 963 fibril_mutex_lock(&conn->rcv_buf_lock); 1054 964 conn->rcv_buf_fin = true; 1055 965 fibril_condvar_broadcast(&conn->rcv_buf_cv); 966 fibril_mutex_unlock(&conn->rcv_buf_lock); 1056 967 1057 968 tcp_segment_delete(seg); … … 1162 1073 log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn); 1163 1074 1164 fibril_mutex_lock(&conn->lock);1165 1166 1075 if (conn->cstate == st_closed) { 1167 1076 log_msg(LVL_DEBUG, "Connection already closed."); 1168 fibril_mutex_unlock(&conn->lock);1169 tcp_conn_delref(conn);1170 1077 return; 1171 1078 } … … 1174 1081 tcp_conn_remove(conn); 1175 1082 tcp_conn_state_set(conn, st_closed); 1176 1177 fibril_mutex_unlock(&conn->lock);1178 tcp_conn_delref(conn);1179 1083 } 1180 1084 … … 1185 1089 void tcp_conn_tw_timer_set(tcp_conn_t *conn) 1186 1090 { 1187 tcp_conn_addref(conn);1188 1091 fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func, 1189 1092 (void *)conn); … … 1196 1099 void tcp_conn_tw_timer_clear(tcp_conn_t *conn) 1197 1100 { 1198 if (fibril_timer_clear(conn->tw_timer) == fts_active) 1199 tcp_conn_delref(conn); 1101 fibril_timer_clear(conn->tw_timer); 1200 1102 } 1201 1103 -
uspace/srv/net/tl/tcp/conn.h
ra438de48 r58f6229 40 40 41 41 extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *); 42 extern void tcp_conn_delete(tcp_conn_t *);43 42 extern void tcp_conn_add(tcp_conn_t *); 44 43 extern void tcp_conn_remove(tcp_conn_t *); … … 46 45 extern void tcp_conn_fin_sent(tcp_conn_t *); 47 46 extern void tcp_conn_ack_of_fin_rcvd(tcp_conn_t *); 48 extern tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *); 49 extern void tcp_conn_addref(tcp_conn_t *); 50 extern void tcp_conn_delref(tcp_conn_t *); 47 extern tcp_conn_t *tcp_conn_find(tcp_sockpair_t *); 51 48 extern bool tcp_conn_got_syn(tcp_conn_t *); 52 49 extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *); -
uspace/srv/net/tl/tcp/sock.c
ra438de48 r58f6229 603 603 604 604 socket = (tcp_sockdata_t *)sock_core->specific_data; 605 606 if (socket->conn != NULL) { 607 trc = tcp_uc_close(socket->conn); 608 if (trc != TCP_EOK && trc != TCP_ENOTEXIST) { 609 async_answer_0(callid, EBADF); 610 return; 611 } 612 613 /* Drain incoming data. This should really be done in the background. */ 614 do { 615 trc = tcp_uc_receive(socket->conn, buffer, 616 FRAGMENT_SIZE, &data_len, &xflags); 617 } while (trc == TCP_EOK); 618 619 tcp_uc_delete(socket->conn); 620 } 605 rc = tcp_uc_close(socket->conn); 606 if (rc != EOK) { 607 async_answer_0(callid, rc); 608 return; 609 } 610 611 /* Drain incoming data. This should really be done in the background. */ 612 do { 613 trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, 614 &data_len, &xflags); 615 } while (trc == TCP_EOK); 621 616 622 617 rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock, -
uspace/srv/net/tl/tcp/tcp_type.h
ra438de48 r58f6229 162 162 acpass_t ap; 163 163 164 /** Protects access to connection structure */165 fibril_mutex_t lock;166 /** Reference count */167 atomic_t refcnt;168 169 164 /** Connection state */ 170 165 tcp_cstate_t cstate; 171 166 /** True if connection was reset */ 172 167 bool reset; 173 /** True if connection was deleted by user*/174 bool deleted;168 /** Protects @c cstate */ 169 fibril_mutex_t cstate_lock; 175 170 /** Signalled when @c cstate changes */ 176 171 fibril_condvar_t cstate_cv; … … 196 191 /** Receive buffer contains FIN */ 197 192 bool rcv_buf_fin; 193 /** Receive buffer lock */ 194 fibril_mutex_t rcv_buf_lock; 198 195 /** Receive buffer CV. Broadcast when new data is inserted */ 199 196 fibril_condvar_t rcv_buf_cv; … … 207 204 /** Send buffer contains FIN */ 208 205 bool snd_buf_fin; 209 /** Send buffer CV. Broadcast when space is made available in buffer */210 fibril_condvar_t snd_buf_cv;211 206 212 207 /** Send unacknowledged */ -
uspace/srv/net/tl/tcp/tqueue.c
ra438de48 r58f6229 188 188 /* We are sending out FIN */ 189 189 ctrl = CTL_FIN; 190 tcp_conn_fin_sent(conn); 190 191 } else { 191 192 ctrl = 0; … … 205 206 if (send_fin) 206 207 conn->snd_buf_fin = false; 207 208 fibril_condvar_broadcast(&conn->snd_buf_cv);209 210 if (send_fin)211 tcp_conn_fin_sent(conn);212 208 213 209 tcp_tqueue_seg(conn, seg); … … 317 313 log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn); 318 314 319 fibril_mutex_lock(&conn->lock);320 321 315 if (conn->cstate == st_closed) { 322 316 log_msg(LVL_DEBUG, "Connection already closed."); 323 fibril_mutex_unlock(&conn->lock);324 tcp_conn_delref(conn);325 317 return; 326 318 } … … 329 321 if (link == NULL) { 330 322 log_msg(LVL_DEBUG, "Nothing to retransmit"); 331 fibril_mutex_unlock(&conn->lock);332 tcp_conn_delref(conn);333 323 return; 334 324 } … … 339 329 if (rt_seg == NULL) { 340 330 log_msg(LVL_ERROR, "Memory allocation failed."); 341 fibril_mutex_unlock(&conn->lock);342 tcp_conn_delref(conn);343 331 /* XXX Handle properly */ 344 332 return; … … 350 338 /* Reset retransmission timer */ 351 339 tcp_tqueue_timer_set(tqe->conn); 352 353 fibril_mutex_unlock(&conn->lock);354 tcp_conn_delref(conn);355 340 } 356 341 … … 360 345 log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name); 361 346 362 /* Clear first to make sure we update refcnt correctly */ 363 tcp_tqueue_timer_clear(conn); 364 365 tcp_conn_addref(conn); 347 (void) retransmit_timeout_func; 366 348 fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT, 367 349 retransmit_timeout_func, (void *) conn); … … 373 355 log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name); 374 356 375 if (fibril_timer_clear(conn->retransmit.timer) == fts_active) 376 tcp_conn_delref(conn); 357 fibril_timer_clear(conn->retransmit.timer); 377 358 } 378 359 -
uspace/srv/net/tl/tcp/ucall.c
ra438de48 r58f6229 83 83 /* Wait for connection to be established or reset */ 84 84 log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection."); 85 fibril_mutex_lock(&nconn-> lock);85 fibril_mutex_lock(&nconn->cstate_lock); 86 86 while (nconn->cstate == st_listen || 87 87 nconn->cstate == st_syn_sent || 88 88 nconn->cstate == st_syn_received) { 89 fibril_condvar_wait(&nconn->cstate_cv, &nconn-> lock);89 fibril_condvar_wait(&nconn->cstate_cv, &nconn->cstate_lock); 90 90 } 91 91 … … 93 93 log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset."); 94 94 assert(nconn->cstate == st_closed); 95 fibril_mutex_unlock(&nconn-> lock);95 fibril_mutex_unlock(&nconn->cstate_lock); 96 96 return TCP_ERESET; 97 97 } 98 98 99 fibril_mutex_unlock(&nconn-> lock);99 fibril_mutex_unlock(&nconn->cstate_lock); 100 100 log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established."); 101 101 … … 113 113 log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name); 114 114 115 fibril_mutex_lock(&conn->lock); 116 117 if (conn->cstate == st_closed) { 118 fibril_mutex_unlock(&conn->lock); 115 if (conn->cstate == st_closed) 119 116 return TCP_ENOTEXIST; 120 }121 117 122 118 if (conn->cstate == st_listen) { … … 125 121 } 126 122 127 128 if (conn->snd_buf_fin) { 129 fibril_mutex_unlock(&conn->lock); 123 if (conn->snd_buf_fin) 130 124 return TCP_ECLOSING; 131 }132 125 133 126 while (size > 0) { 134 127 buf_free = conn->snd_buf_size - conn->snd_buf_used; 135 while (buf_free == 0 && !conn->reset) { 136 log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.", 137 conn->name); 138 fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock); 139 buf_free = conn->snd_buf_size - conn->snd_buf_used; 140 } 141 142 if (conn->reset) { 143 fibril_mutex_unlock(&conn->lock); 128 while (buf_free == 0 && !conn->reset) 129 tcp_tqueue_new_data(conn); 130 131 if (conn->reset) 144 132 return TCP_ERESET; 145 }146 133 147 134 xfer_size = min(size, buf_free); … … 152 139 conn->snd_buf_used += xfer_size; 153 140 size -= xfer_size; 154 155 tcp_tqueue_new_data(conn);156 141 } 157 142 158 143 tcp_tqueue_new_data(conn); 159 fibril_mutex_unlock(&conn->lock);160 144 161 145 return TCP_EOK; … … 170 154 log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name); 171 155 172 fibril_mutex_lock(&conn->lock); 173 174 if (conn->cstate == st_closed) { 175 fibril_mutex_unlock(&conn->lock); 156 if (conn->cstate == st_closed) 176 157 return TCP_ENOTEXIST; 177 } 158 159 fibril_mutex_lock(&conn->rcv_buf_lock); 178 160 179 161 /* Wait for data to become available */ 180 162 while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) { 181 163 log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data"); 182 fibril_condvar_wait(&conn->rcv_buf_cv, &conn-> lock);164 fibril_condvar_wait(&conn->rcv_buf_cv, &conn->rcv_buf_lock); 183 165 } 184 166 185 167 if (conn->rcv_buf_used == 0) { 168 fibril_mutex_unlock(&conn->rcv_buf_lock); 169 186 170 *rcvd = 0; 187 171 *xflags = 0; … … 189 173 if (conn->rcv_buf_fin) { 190 174 /* End of data, peer closed connection */ 191 fibril_mutex_unlock(&conn->lock);192 175 return TCP_ECLOSING; 193 176 } else { 194 177 /* Connection was reset */ 195 178 assert(conn->reset); 196 fibril_mutex_unlock(&conn->lock);197 179 return TCP_ERESET; 198 180 } … … 210 192 conn->rcv_wnd += xfer_size; 211 193 194 fibril_mutex_unlock(&conn->rcv_buf_lock); 195 212 196 /* TODO */ 213 197 *xflags = 0; … … 219 203 conn->name, xfer_size); 220 204 221 fibril_mutex_unlock(&conn->lock);222 223 205 return TCP_EOK; 224 206 } … … 229 211 log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name); 230 212 231 fibril_mutex_lock(&conn->lock); 232 233 if (conn->cstate == st_closed) { 234 fibril_mutex_unlock(&conn->lock); 213 if (conn->cstate == st_closed) 235 214 return TCP_ENOTEXIST; 236 } 237 238 if (conn->snd_buf_fin) { 239 fibril_mutex_unlock(&conn->lock); 215 216 if (conn->snd_buf_fin) 240 217 return TCP_ECLOSING; 241 }242 218 243 219 conn->snd_buf_fin = true; 244 220 tcp_tqueue_new_data(conn); 245 221 246 fibril_mutex_unlock(&conn->lock);247 222 return TCP_EOK; 248 223 } … … 260 235 } 261 236 262 /** Delete connection user call.263 *264 * (Not in spec.) Inform TCP that the user is done with this connection265 * and will not make any further calls/references to it. TCP can deallocate266 * the connection from now on.267 */268 void tcp_uc_delete(tcp_conn_t *conn)269 {270 log_msg(LVL_DEBUG, "tcp_uc_delete()");271 tcp_conn_delete(conn);272 }273 237 274 238 /* … … 285 249 sp->local.addr.ipv4, sp->local.port); 286 250 287 conn = tcp_conn_find_ref(sp); 288 if (conn == NULL) { 289 log_msg(LVL_WARN, "No connection found."); 251 conn = tcp_conn_find(sp); 252 if (conn != NULL && conn->cstate != st_closed) { 253 if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY) 254 conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4; 255 if (conn->ident.foreign.port == TCP_PORT_ANY) 256 conn->ident.foreign.port = sp->foreign.port; 257 if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY) 258 conn->ident.local.addr.ipv4 = sp->local.addr.ipv4; 259 260 tcp_conn_segment_arrived(conn, seg); 261 } else { 262 if (conn == NULL) 263 log_msg(LVL_WARN, "No connection found."); 264 else 265 log_msg(LVL_WARN, "Connection is closed."); 290 266 tcp_unexpected_segment(sp, seg); 291 return; 292 } 293 294 fibril_mutex_lock(&conn->lock); 295 296 if (conn->cstate == st_closed) { 297 log_msg(LVL_WARN, "Connection is closed."); 298 tcp_unexpected_segment(sp, seg); 299 fibril_mutex_unlock(&conn->lock); 300 tcp_conn_delref(conn); 301 return; 302 } 303 304 if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY) 305 conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4; 306 if (conn->ident.foreign.port == TCP_PORT_ANY) 307 conn->ident.foreign.port = sp->foreign.port; 308 if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY) 309 conn->ident.local.addr.ipv4 = sp->local.addr.ipv4; 310 311 tcp_conn_segment_arrived(conn, seg); 312 313 fibril_mutex_unlock(&conn->lock); 314 tcp_conn_delref(conn); 267 } 315 268 } 316 269 -
uspace/srv/net/tl/tcp/ucall.h
ra438de48 r58f6229 48 48 extern void tcp_uc_abort(tcp_conn_t *); 49 49 extern void tcp_uc_status(tcp_conn_t *, tcp_conn_status_t *); 50 extern void tcp_uc_delete(tcp_conn_t *);51 50 52 51 /*
Note:
See TracChangeset
for help on using the changeset viewer.
