Changeset cf3aee19 in mainline for uspace/srv/net/tcp/conn.c
- Timestamp:
- 2015-06-17T23:45:24Z (9 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 523b17a
- Parents:
- fc7bf19 (diff), 2654afb (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tcp/conn.c
rfc7bf19 rcf3aee19 1 1 /* 2 * Copyright (c) 201 1Jiri Svoboda2 * Copyright (c) 2015 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 36 36 37 37 #include <adt/list.h> 38 #include <stdbool.h>39 38 #include <errno.h> 39 #include <inet/endpoint.h> 40 40 #include <io/log.h> 41 41 #include <macros.h> 42 #include <nettl/amap.h> 43 #include <stdbool.h> 42 44 #include <stdlib.h> 43 45 #include "conn.h" … … 55 57 #define TIME_WAIT_TIMEOUT (2*MAX_SEGMENT_LIFETIME) 56 58 57 LIST_INITIALIZE(conn_list); 58 FIBRIL_MUTEX_INITIALIZE(conn_list_lock); 59 static LIST_INITIALIZE(conn_list); 60 /** Taken after tcp_conn_t lock */ 61 static FIBRIL_MUTEX_INITIALIZE(conn_list_lock); 62 static amap_t *amap; 59 63 60 64 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg); … … 62 66 static void tcp_conn_tw_timer_clear(tcp_conn_t *conn); 63 67 68 /** Initialize connections. */ 69 int tcp_conns_init(void) 70 { 71 int rc; 72 73 rc = amap_create(&amap); 74 if (rc != EOK) { 75 assert(rc == ENOMEM); 76 return ENOMEM; 77 } 78 79 return EOK; 80 } 81 64 82 /** Create new connection structure. 65 83 * 66 * @param lsock Local socket (will be deeply copied) 67 * @param fsock Foreign socket (will be deeply copied) 84 * @param epp Endpoint pair (will be deeply copied) 68 85 * @return New connection or NULL 69 86 */ 70 tcp_conn_t *tcp_conn_new( tcp_sock_t *lsock, tcp_sock_t *fsock)87 tcp_conn_t *tcp_conn_new(inet_ep2_t *epp) 71 88 { 72 89 tcp_conn_t *conn = NULL; … … 121 138 fibril_condvar_initialize(&conn->cstate_cv); 122 139 123 conn->c state_cb = NULL;140 conn->cb = NULL; 124 141 125 142 conn->cstate = st_listen; … … 128 145 conn->ap = ap_passive; 129 146 conn->fin_is_acked = false; 130 conn->ident.local = *lsock; 131 if (fsock != NULL) 132 conn->ident.foreign = *fsock; 147 if (epp != NULL) 148 conn->ident = *epp; 133 149 134 150 return conn; … … 184 200 void tcp_conn_addref(tcp_conn_t *conn) 185 201 { 186 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn); 202 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p) before=%zu", 203 conn->name, conn, atomic_get(&conn->refcnt)); 187 204 atomic_inc(&conn->refcnt); 188 205 } … … 196 213 void tcp_conn_delref(tcp_conn_t *conn) 197 214 { 198 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn); 215 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p) before=%zu", 216 conn->name, conn, atomic_get(&conn->refcnt)); 199 217 200 218 if (atomic_predec(&conn->refcnt) == 0) … … 237 255 238 256 assert(conn->deleted == false); 257 conn->deleted = true; 258 conn->cb = NULL; 259 conn->cb_arg = NULL; 239 260 tcp_conn_delref(conn); 240 261 } … … 244 265 * Add connection to the connection map. 245 266 */ 246 void tcp_conn_add(tcp_conn_t *conn) 247 { 267 int tcp_conn_add(tcp_conn_t *conn) 268 { 269 inet_ep2_t aepp; 270 int rc; 271 248 272 tcp_conn_addref(conn); 249 273 fibril_mutex_lock(&conn_list_lock); 274 275 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_add: conn=%p", conn); 276 277 rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp); 278 if (rc != EOK) { 279 tcp_conn_delref(conn); 280 fibril_mutex_unlock(&conn_list_lock); 281 return rc; 282 } 283 284 conn->ident = aepp; 250 285 list_append(&conn->link, &conn_list); 251 286 fibril_mutex_unlock(&conn_list_lock); 287 288 return EOK; 252 289 } 253 290 … … 259 296 { 260 297 fibril_mutex_lock(&conn_list_lock); 298 amap_remove(amap, &conn->ident); 261 299 list_remove(&conn->link); 262 300 fibril_mutex_unlock(&conn_list_lock); … … 275 313 276 314 /* Run user callback function */ 277 if (conn->c state_cb!= NULL) {315 if (conn->cb != NULL && conn->cb->cstate_change != NULL) { 278 316 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - run user CB"); 279 conn->c state_cb(conn, conn->cstate_cb_arg);317 conn->cb->cstate_change(conn, conn->cb_arg, old_state); 280 318 } else { 281 319 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - no user CB"); … … 284 322 assert(old_state != st_closed); 285 323 if (nstate == st_closed) { 324 tcp_conn_remove(conn); 286 325 /* Drop one reference for now being in closed state */ 287 326 tcp_conn_delref(conn); … … 332 371 } 333 372 334 /** Match socket with pattern. */ 335 static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt) 336 { 337 log_msg(LOG_DEFAULT, LVL_DEBUG2, 338 "tcp_socket_match(sock=(%u), pat=(%u))", sock->port, patt->port); 339 340 if ((!inet_addr_is_any(&patt->addr)) && 341 (!inet_addr_compare(&patt->addr, &sock->addr))) 342 return false; 343 344 if ((patt->port != TCP_PORT_ANY) && 345 (patt->port != sock->port)) 346 return false; 347 348 log_msg(LOG_DEFAULT, LVL_DEBUG2, " -> match"); 349 350 return true; 351 } 352 353 /** Match socket pair with pattern. */ 354 static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern) 355 { 356 log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_sockpair_match(%p, %p)", sp, pattern); 357 358 if (!tcp_socket_match(&sp->local, &pattern->local)) 359 return false; 360 361 if (!tcp_socket_match(&sp->foreign, &pattern->foreign)) 362 return false; 363 364 return true; 365 } 366 367 /** Find connection structure for specified socket pair. 368 * 369 * A connection is uniquely identified by a socket pair. Look up our 370 * connection map and return connection structure based on socket pair. 373 /** Find connection structure for specified endpoint pair. 374 * 375 * A connection is uniquely identified by a endpoint pair. Look up our 376 * connection map and return connection structure based on endpoint pair. 371 377 * The connection reference count is bumped by one. 372 378 * 373 * @param sp Socket pair379 * @param epp Endpoint pair 374 380 * @return Connection structure or NULL if not found. 375 381 */ 376 tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp) 377 { 378 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", sp); 379 380 log_msg(LOG_DEFAULT, LVL_DEBUG2, "compare conn (f:(%u), l:(%u))", 381 sp->foreign.port, sp->local.port); 382 382 tcp_conn_t *tcp_conn_find_ref(inet_ep2_t *epp) 383 { 384 int rc; 385 void *arg; 386 tcp_conn_t *conn; 387 388 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", epp); 389 383 390 fibril_mutex_lock(&conn_list_lock); 384 385 list_foreach(conn_list, link, tcp_conn_t, conn) { 386 tcp_sockpair_t *csp = &conn->ident; 387 388 log_msg(LOG_DEFAULT, LVL_DEBUG2, " - with (f:(%u), l:(%u))", 389 csp->foreign.port, csp->local.port); 390 391 if (tcp_sockpair_match(sp, csp)) { 392 tcp_conn_addref(conn); 393 fibril_mutex_unlock(&conn_list_lock); 394 return conn; 395 } 396 } 397 391 392 rc = amap_find_match(amap, epp, &arg); 393 if (rc != EOK) { 394 assert(rc == ENOENT); 395 fibril_mutex_unlock(&conn_list_lock); 396 return NULL; 397 } 398 399 conn = (tcp_conn_t *)arg; 400 tcp_conn_addref(conn); 401 398 402 fibril_mutex_unlock(&conn_list_lock); 399 return NULL; 403 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref: got conn=%p", 404 conn); 405 return conn; 400 406 } 401 407 … … 407 413 { 408 414 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_reset()", conn->name); 415 conn->reset = true; 409 416 tcp_conn_state_set(conn, st_closed); 410 conn->reset = true;411 417 412 418 tcp_conn_tw_timer_clear(conn); … … 877 883 if (conn->fin_is_acked) { 878 884 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Closed", conn->name); 879 tcp_conn_remove(conn);880 885 tcp_conn_state_set(conn, st_closed); 881 886 return cp_done; … … 1006 1011 1007 1012 /* Signal to the receive function that new data has arrived */ 1008 fibril_condvar_broadcast(&conn->rcv_buf_cv); 1013 if (xfer_size > 0) { 1014 fibril_condvar_broadcast(&conn->rcv_buf_cv); 1015 if (conn->cb != NULL && conn->cb->recv_data != NULL) 1016 conn->cb->recv_data(conn, conn->cb_arg); 1017 } 1009 1018 1010 1019 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes of data.", xfer_size); … … 1098 1107 conn->rcv_buf_fin = true; 1099 1108 fibril_condvar_broadcast(&conn->rcv_buf_cv); 1109 if (conn->cb != NULL && conn->cb->recv_data != NULL) 1110 conn->cb->recv_data(conn, conn->cb_arg); 1100 1111 1101 1112 tcp_segment_delete(seg); … … 1168 1179 * 1169 1180 * @param conn Connection 1170 * @param seg Segment 1171 */ 1172 void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg) 1173 { 1181 * @param epp Endpoint pair on which segment was received 1182 * @param seg Segment 1183 */ 1184 void tcp_conn_segment_arrived(tcp_conn_t *conn, inet_ep2_t *epp, 1185 tcp_segment_t *seg) 1186 { 1187 inet_ep2_t aepp; 1188 inet_ep2_t oldepp; 1189 int rc; 1190 1174 1191 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)", 1175 1192 conn->name, seg); 1176 1193 1194 tcp_conn_lock(conn); 1195 1196 if (conn->cstate == st_closed) { 1197 log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed."); 1198 tcp_unexpected_segment(epp, seg); 1199 tcp_conn_unlock(conn); 1200 return; 1201 } 1202 1203 if (inet_addr_is_any(&conn->ident.remote.addr) || 1204 conn->ident.remote.port == inet_port_any || 1205 inet_addr_is_any(&conn->ident.local.addr)) { 1206 1207 log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_segment_arrived: " 1208 "Changing connection ID, updating amap."); 1209 oldepp = conn->ident; 1210 1211 /* Need to remove and re-insert connection with new identity */ 1212 fibril_mutex_lock(&conn_list_lock); 1213 1214 if (inet_addr_is_any(&conn->ident.remote.addr)) 1215 conn->ident.remote.addr = epp->remote.addr; 1216 1217 if (conn->ident.remote.port == inet_port_any) 1218 conn->ident.remote.port = epp->remote.port; 1219 1220 if (inet_addr_is_any(&conn->ident.local.addr)) 1221 conn->ident.local.addr = epp->local.addr; 1222 1223 rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp); 1224 if (rc != EOK) { 1225 assert(rc != EEXISTS); 1226 assert(rc == ENOMEM); 1227 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory."); 1228 fibril_mutex_unlock(&conn_list_lock); 1229 tcp_conn_unlock(conn); 1230 return; 1231 } 1232 1233 amap_remove(amap, &oldepp); 1234 fibril_mutex_unlock(&conn_list_lock); 1235 1236 conn->name = (char *) "a"; 1237 } 1238 1177 1239 switch (conn->cstate) { 1178 1240 case st_listen: 1179 tcp_conn_sa_listen(conn, seg); break; 1241 tcp_conn_sa_listen(conn, seg); 1242 break; 1180 1243 case st_syn_sent: 1181 tcp_conn_sa_syn_sent(conn, seg); break; 1244 tcp_conn_sa_syn_sent(conn, seg); 1245 break; 1182 1246 case st_syn_received: 1183 1247 case st_established: … … 1189 1253 case st_time_wait: 1190 1254 /* Process segments in order of sequence number */ 1191 tcp_conn_sa_queue(conn, seg); break; 1255 tcp_conn_sa_queue(conn, seg); 1256 break; 1192 1257 case st_closed: 1193 1258 log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate); 1194 1259 assert(false); 1195 1260 } 1261 1262 tcp_conn_unlock(conn); 1196 1263 } 1197 1264 … … 1216 1283 1217 1284 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name); 1218 tcp_conn_remove(conn);1219 1285 tcp_conn_state_set(conn, st_closed); 1220 1286 … … 1263 1329 } 1264 1330 1265 /** Handle unexpected segment received on a socket pair.1331 /** Handle unexpected segment received on an endpoint pair. 1266 1332 * 1267 1333 * We reply with an RST unless the received segment has RST. 1268 1334 * 1269 * @param sp Socket pair which received the segment1335 * @param sp Endpoint pair which received the segment 1270 1336 * @param seg Unexpected segment 1271 1337 */ 1272 void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg) 1273 { 1274 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg); 1338 void tcp_unexpected_segment(inet_ep2_t *epp, tcp_segment_t *seg) 1339 { 1340 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", epp, 1341 seg); 1275 1342 1276 1343 if ((seg->ctrl & CTL_RST) == 0) 1277 tcp_reply_rst( sp, seg);1278 } 1279 1280 /** Compute flipped socket pair for response.1281 * 1282 * Flipped socket pair has local and foreign sockets exchanged.1283 * 1284 * @param sp Socket pair1285 * @param f sp Place to store flipped socket pair1286 */ 1287 void tcp_ sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)1288 { 1289 f sp->local = sp->foreign;1290 f sp->foreign = sp->local;1344 tcp_reply_rst(epp, seg); 1345 } 1346 1347 /** Compute flipped endpoint pair for response. 1348 * 1349 * Flipped endpoint pair has local and remote endpoints exchanged. 1350 * 1351 * @param epp Endpoint pair 1352 * @param fepp Place to store flipped endpoint pair 1353 */ 1354 void tcp_ep2_flipped(inet_ep2_t *epp, inet_ep2_t *fepp) 1355 { 1356 fepp->local = epp->remote; 1357 fepp->remote = epp->local; 1291 1358 } 1292 1359 1293 1360 /** Send RST in response to an incoming segment. 1294 1361 * 1295 * @param sp Socket pair which received the segment1362 * @param epp Endpoint pair which received the segment 1296 1363 * @param seg Incoming segment 1297 1364 */ 1298 void tcp_reply_rst( tcp_sockpair_t *sp, tcp_segment_t *seg)1365 void tcp_reply_rst(inet_ep2_t *epp, tcp_segment_t *seg) 1299 1366 { 1300 1367 tcp_segment_t *rseg; 1301 1368 1302 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);1369 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", epp, seg); 1303 1370 1304 1371 rseg = tcp_segment_make_rst(seg); 1305 tcp_transmit_segment( sp, rseg);1372 tcp_transmit_segment(epp, rseg); 1306 1373 } 1307 1374
Note:
See TracChangeset
for help on using the changeset viewer.