Changes in uspace/srv/net/tcp/conn.c [c3f7d37:78192cc7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tcp/conn.c
rc3f7d37 r78192cc7 1 1 /* 2 * Copyright (c) 201 5Jiri Svoboda2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 36 36 37 37 #include <adt/list.h> 38 #include <stdbool.h> 38 39 #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>44 42 #include <stdlib.h> 45 43 #include "conn.h" … … 57 55 #define TIME_WAIT_TIMEOUT (2*MAX_SEGMENT_LIFETIME) 58 56 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; 57 LIST_INITIALIZE(conn_list); 58 FIBRIL_MUTEX_INITIALIZE(conn_list_lock); 63 59 64 60 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg); … … 66 62 static void tcp_conn_tw_timer_clear(tcp_conn_t *conn); 67 63 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 82 64 /** Create new connection structure. 83 65 * 84 * @param epp Endpoint pair (will be deeply copied) 66 * @param lsock Local socket (will be deeply copied) 67 * @param fsock Foreign socket (will be deeply copied) 85 68 * @return New connection or NULL 86 69 */ 87 tcp_conn_t *tcp_conn_new( inet_ep2_t *epp)70 tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock) 88 71 { 89 72 tcp_conn_t *conn = NULL; … … 138 121 fibril_condvar_initialize(&conn->cstate_cv); 139 122 140 conn->c b = NULL;123 conn->cstate_cb = NULL; 141 124 142 125 conn->cstate = st_listen; … … 145 128 conn->ap = ap_passive; 146 129 conn->fin_is_acked = false; 147 if (epp != NULL) 148 conn->ident = *epp; 130 conn->ident.local = *lsock; 131 if (fsock != NULL) 132 conn->ident.foreign = *fsock; 149 133 150 134 return conn; … … 200 184 void tcp_conn_addref(tcp_conn_t *conn) 201 185 { 202 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p) before=%zu", 203 conn->name, conn, atomic_get(&conn->refcnt)); 186 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn); 204 187 atomic_inc(&conn->refcnt); 205 188 } … … 213 196 void tcp_conn_delref(tcp_conn_t *conn) 214 197 { 215 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p) before=%zu", 216 conn->name, conn, atomic_get(&conn->refcnt)); 198 log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn); 217 199 218 200 if (atomic_predec(&conn->refcnt) == 0) … … 255 237 256 238 assert(conn->deleted == false); 257 conn->deleted = true;258 conn->cb = NULL;259 conn->cb_arg = NULL;260 239 tcp_conn_delref(conn); 261 240 } … … 265 244 * Add connection to the connection map. 266 245 */ 267 int tcp_conn_add(tcp_conn_t *conn) 268 { 269 inet_ep2_t aepp; 270 int rc; 271 246 void tcp_conn_add(tcp_conn_t *conn) 247 { 272 248 tcp_conn_addref(conn); 273 249 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;285 250 list_append(&conn->link, &conn_list); 286 251 fibril_mutex_unlock(&conn_list_lock); 287 288 return EOK;289 252 } 290 253 … … 296 259 { 297 260 fibril_mutex_lock(&conn_list_lock); 298 amap_remove(amap, &conn->ident);299 261 list_remove(&conn->link); 300 262 fibril_mutex_unlock(&conn_list_lock); … … 313 275 314 276 /* Run user callback function */ 315 if (conn->c b != NULL && conn->cb->cstate_change!= NULL) {277 if (conn->cstate_cb != NULL) { 316 278 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - run user CB"); 317 conn->c b->cstate_change(conn, conn->cb_arg, old_state);279 conn->cstate_cb(conn, conn->cstate_cb_arg); 318 280 } else { 319 281 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - no user CB"); … … 322 284 assert(old_state != st_closed); 323 285 if (nstate == st_closed) { 324 tcp_conn_remove(conn);325 286 /* Drop one reference for now being in closed state */ 326 287 tcp_conn_delref(conn); … … 371 332 } 372 333 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. 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. 377 371 * The connection reference count is bumped by one. 378 372 * 379 * @param epp Endpoint pair373 * @param sp Socket pair 380 374 * @return Connection structure or NULL if not found. 381 375 */ 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 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 390 383 fibril_mutex_lock(&conn_list_lock); 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 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 402 398 fibril_mutex_unlock(&conn_list_lock); 403 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref: got conn=%p", 404 conn); 405 return conn; 399 return NULL; 406 400 } 407 401 … … 413 407 { 414 408 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_reset()", conn->name); 409 tcp_conn_state_set(conn, st_closed); 415 410 conn->reset = true; 416 tcp_conn_state_set(conn, st_closed);417 411 418 412 tcp_conn_tw_timer_clear(conn); … … 883 877 if (conn->fin_is_acked) { 884 878 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Closed", conn->name); 879 tcp_conn_remove(conn); 885 880 tcp_conn_state_set(conn, st_closed); 886 881 return cp_done; … … 1012 1007 /* Signal to the receive function that new data has arrived */ 1013 1008 fibril_condvar_broadcast(&conn->rcv_buf_cv); 1014 if (conn->cb != NULL && conn->cb->recv_data != NULL)1015 conn->cb->recv_data(conn, conn->cb_arg);1016 1009 1017 1010 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes of data.", xfer_size); … … 1105 1098 conn->rcv_buf_fin = true; 1106 1099 fibril_condvar_broadcast(&conn->rcv_buf_cv); 1107 if (conn->cb != NULL && conn->cb->recv_data != NULL)1108 conn->cb->recv_data(conn, conn->cb_arg);1109 1100 1110 1101 tcp_segment_delete(seg); … … 1177 1168 * 1178 1169 * @param conn Connection 1179 * @param epp Endpoint pair on which segment was received 1180 * @param seg Segment 1181 */ 1182 void tcp_conn_segment_arrived(tcp_conn_t *conn, inet_ep2_t *epp, 1183 tcp_segment_t *seg) 1184 { 1185 inet_ep2_t aepp; 1186 inet_ep2_t oldepp; 1187 int rc; 1188 1170 * @param seg Segment 1171 */ 1172 void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg) 1173 { 1189 1174 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)", 1190 1175 conn->name, seg); 1191 1176 1192 tcp_conn_lock(conn);1193 1194 if (conn->cstate == st_closed) {1195 log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");1196 tcp_unexpected_segment(epp, seg);1197 tcp_conn_unlock(conn);1198 return;1199 }1200 1201 if (inet_addr_is_any(&conn->ident.remote.addr) ||1202 conn->ident.remote.port == inet_port_any ||1203 inet_addr_is_any(&conn->ident.local.addr)) {1204 1205 log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_segment_arrived: "1206 "Changing connection ID, updating amap.");1207 oldepp = conn->ident;1208 1209 /* Need to remove and re-insert connection with new identity */1210 fibril_mutex_lock(&conn_list_lock);1211 1212 if (inet_addr_is_any(&conn->ident.remote.addr))1213 conn->ident.remote.addr = epp->remote.addr;1214 1215 if (conn->ident.remote.port == inet_port_any)1216 conn->ident.remote.port = epp->remote.port;1217 1218 if (inet_addr_is_any(&conn->ident.local.addr))1219 conn->ident.local.addr = epp->local.addr;1220 1221 rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp);1222 if (rc != EOK) {1223 assert(rc != EEXISTS);1224 assert(rc == ENOMEM);1225 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");1226 fibril_mutex_unlock(&conn_list_lock);1227 tcp_conn_unlock(conn);1228 return;1229 }1230 1231 amap_remove(amap, &oldepp);1232 fibril_mutex_unlock(&conn_list_lock);1233 1234 conn->name = (char *) "a";1235 }1236 1237 1177 switch (conn->cstate) { 1238 1178 case st_listen: 1239 tcp_conn_sa_listen(conn, seg); 1240 break; 1179 tcp_conn_sa_listen(conn, seg); break; 1241 1180 case st_syn_sent: 1242 tcp_conn_sa_syn_sent(conn, seg); 1243 break; 1181 tcp_conn_sa_syn_sent(conn, seg); break; 1244 1182 case st_syn_received: 1245 1183 case st_established: … … 1251 1189 case st_time_wait: 1252 1190 /* Process segments in order of sequence number */ 1253 tcp_conn_sa_queue(conn, seg); 1254 break; 1191 tcp_conn_sa_queue(conn, seg); break; 1255 1192 case st_closed: 1256 1193 log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate); 1257 1194 assert(false); 1258 1195 } 1259 1260 tcp_conn_unlock(conn);1261 1196 } 1262 1197 … … 1281 1216 1282 1217 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name); 1218 tcp_conn_remove(conn); 1283 1219 tcp_conn_state_set(conn, st_closed); 1284 1220 … … 1327 1263 } 1328 1264 1329 /** Handle unexpected segment received on a n endpoint pair.1265 /** Handle unexpected segment received on a socket pair. 1330 1266 * 1331 1267 * We reply with an RST unless the received segment has RST. 1332 1268 * 1333 * @param sp Endpoint pair which received the segment1269 * @param sp Socket pair which received the segment 1334 1270 * @param seg Unexpected segment 1335 1271 */ 1336 void tcp_unexpected_segment(inet_ep2_t *epp, tcp_segment_t *seg) 1337 { 1338 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", epp, 1339 seg); 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); 1340 1275 1341 1276 if ((seg->ctrl & CTL_RST) == 0) 1342 tcp_reply_rst( epp, seg);1343 } 1344 1345 /** Compute flipped endpoint pair for response.1346 * 1347 * Flipped endpoint pair has local and remote endpoints exchanged.1348 * 1349 * @param epp Endpoint pair1350 * @param f epp Place to store flipped endpoint pair1351 */ 1352 void tcp_ ep2_flipped(inet_ep2_t *epp, inet_ep2_t *fepp)1353 { 1354 f epp->local = epp->remote;1355 f epp->remote = epp->local;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 pair 1285 * @param fsp Place to store flipped socket pair 1286 */ 1287 void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp) 1288 { 1289 fsp->local = sp->foreign; 1290 fsp->foreign = sp->local; 1356 1291 } 1357 1292 1358 1293 /** Send RST in response to an incoming segment. 1359 1294 * 1360 * @param epp Endpoint pair which received the segment1295 * @param sp Socket pair which received the segment 1361 1296 * @param seg Incoming segment 1362 1297 */ 1363 void tcp_reply_rst( inet_ep2_t *epp, tcp_segment_t *seg)1298 void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg) 1364 1299 { 1365 1300 tcp_segment_t *rseg; 1366 1301 1367 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", epp, seg);1302 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg); 1368 1303 1369 1304 rseg = tcp_segment_make_rst(seg); 1370 tcp_transmit_segment( epp, rseg);1305 tcp_transmit_segment(sp, rseg); 1371 1306 } 1372 1307
Note:
See TracChangeset
for help on using the changeset viewer.