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