Changes in uspace/srv/net/udp/assoc.c [c3f7d37:071a2c60] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/udp/assoc.c
rc3f7d37 r071a2c60 1 1 /* 2 * Copyright (c) 201 5Jiri Svoboda2 * Copyright (c) 2012 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 36 36 37 37 #include <adt/list.h> 38 #include <errno.h>39 38 #include <stdbool.h> 40 39 #include <fibril_synch.h> 41 #include <inet/endpoint.h>42 40 #include <io/log.h> 43 #include <nettl/amap.h>44 41 #include <stdlib.h> 45 42 … … 47 44 #include "msg.h" 48 45 #include "pdu.h" 46 #include "ucall.h" 49 47 #include "udp_inet.h" 50 48 #include "udp_type.h" 51 49 52 static LIST_INITIALIZE(assoc_list); 53 static FIBRIL_MUTEX_INITIALIZE(assoc_list_lock); 54 static amap_t *amap; 55 56 static udp_assoc_t *udp_assoc_find_ref(inet_ep2_t *); 57 static int udp_assoc_queue_msg(udp_assoc_t *, inet_ep2_t *, udp_msg_t *); 58 59 /** Initialize associations. */ 60 int udp_assocs_init(void) 61 { 62 int rc; 63 64 rc = amap_create(&amap); 65 if (rc != EOK) { 66 assert(rc == ENOMEM); 67 return ENOMEM; 68 } 69 70 return EOK; 71 } 50 LIST_INITIALIZE(assoc_list); 51 FIBRIL_MUTEX_INITIALIZE(assoc_list_lock); 52 53 static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *); 54 static int udp_assoc_queue_msg(udp_assoc_t *, udp_sockpair_t *, udp_msg_t *); 55 static bool udp_socket_match(udp_sock_t *, udp_sock_t *); 56 static bool udp_sockpair_match(udp_sockpair_t *, udp_sockpair_t *); 72 57 73 58 /** Create new association structure. 74 59 * 75 * @param epp Endpoint pair (will be copied) 76 * @param cb Callbacks 77 * @param cb_arg Callback argument 60 * @param lsock Local socket (will be deeply copied) 61 * @param fsock Foreign socket (will be deeply copied) 78 62 * @return New association or NULL 79 63 */ 80 udp_assoc_t *udp_assoc_new( inet_ep2_t *epp, udp_assoc_cb_t *cb, void *cb_arg)64 udp_assoc_t *udp_assoc_new(udp_sock_t *lsock, udp_sock_t *fsock) 81 65 { 82 66 udp_assoc_t *assoc = NULL; … … 96 80 fibril_condvar_initialize(&assoc->rcv_queue_cv); 97 81 98 if (epp != NULL) 99 assoc->ident = *epp; 100 101 assoc->cb = cb; 102 assoc->cb_arg = cb_arg; 82 if (lsock != NULL) 83 assoc->ident.local = *lsock; 84 85 if (fsock != NULL) 86 assoc->ident.foreign = *fsock; 87 103 88 return assoc; 104 89 error: … … 181 166 * Add association to the association map. 182 167 */ 183 int udp_assoc_add(udp_assoc_t *assoc) 184 { 185 inet_ep2_t aepp; 186 int rc; 187 168 void udp_assoc_add(udp_assoc_t *assoc) 169 { 188 170 udp_assoc_addref(assoc); 189 171 fibril_mutex_lock(&assoc_list_lock); 190 191 rc = amap_insert(amap, &assoc->ident, assoc, af_allow_system, &aepp);192 if (rc != EOK) {193 udp_assoc_delref(assoc);194 fibril_mutex_unlock(&assoc_list_lock);195 return rc;196 }197 198 assoc->ident = aepp;199 172 list_append(&assoc->link, &assoc_list); 200 173 fibril_mutex_unlock(&assoc_list_lock); 201 202 return EOK;203 174 } 204 175 … … 210 181 { 211 182 fibril_mutex_lock(&assoc_list_lock); 212 amap_remove(amap, &assoc->ident);213 183 list_remove(&assoc->link); 214 184 fibril_mutex_unlock(&assoc_list_lock); … … 226 196 assoc, iplink); 227 197 fibril_mutex_lock(&assoc->lock); 228 assoc->ident.local_link = iplink; 198 assoc->ident.iplink = iplink; 199 fibril_mutex_unlock(&assoc->lock); 200 } 201 202 /** Set foreign socket in association. 203 * 204 * @param assoc Association 205 * @param fsock Foreign socket (deeply copied) 206 */ 207 void udp_assoc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock) 208 { 209 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock); 210 fibril_mutex_lock(&assoc->lock); 211 assoc->ident.foreign = *fsock; 212 fibril_mutex_unlock(&assoc->lock); 213 } 214 215 /** Set local socket in association. 216 * 217 * @param assoc Association 218 * @param lsock Local socket (deeply copied) 219 * 220 */ 221 void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock) 222 { 223 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock); 224 fibril_mutex_lock(&assoc->lock); 225 assoc->ident.local = *lsock; 226 fibril_mutex_unlock(&assoc->lock); 227 } 228 229 /** Set local port in association. 230 * 231 * @param assoc Association 232 * @param lport Local port 233 * 234 */ 235 void udp_assoc_set_local_port(udp_assoc_t *assoc, uint16_t lport) 236 { 237 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %" PRIu16 ")", assoc, lport); 238 fibril_mutex_lock(&assoc->lock); 239 assoc->ident.local.port = lport; 229 240 fibril_mutex_unlock(&assoc->lock); 230 241 } … … 233 244 * 234 245 * @param assoc Association 235 * @param remote Remote endpoint or NULL not to override @a assoc246 * @param fsock Foreign socket or NULL not to override @a assoc 236 247 * @param msg Message 237 248 * 238 249 * @return EOK on success 239 * EINVAL if remote endpoint is not set250 * EINVAL if foreign socket is not set 240 251 * ENOMEM if out of resources 241 252 * EIO if no route to destination exists 242 253 */ 243 int udp_assoc_send(udp_assoc_t *assoc, inet_ep_t *remote, udp_msg_t *msg)254 int udp_assoc_send(udp_assoc_t *assoc, udp_sock_t *fsock, udp_msg_t *msg) 244 255 { 245 256 udp_pdu_t *pdu; 246 inet_ep2_t epp;257 udp_sockpair_t sp; 247 258 int rc; 248 259 249 260 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send(%p, %p, %p)", 250 assoc, remote, msg); 251 252 /* @a remote can be used to override the remote endpoint */ 253 epp = assoc->ident; 254 if (remote != NULL) 255 epp.remote = *remote; 256 257 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - check addr any"); 258 259 if ((inet_addr_is_any(&epp.remote.addr)) || 260 (epp.remote.port == inet_port_any)) 261 assoc, fsock, msg); 262 263 /* @a fsock can be used to override the foreign socket */ 264 sp = assoc->ident; 265 if (fsock != NULL) 266 sp.foreign = *fsock; 267 268 if ((inet_addr_is_any(&sp.foreign.addr)) || 269 (sp.foreign.port == UDP_PORT_ANY)) 261 270 return EINVAL; 262 271 263 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - check version"); 264 265 if (epp.remote.addr.version != epp.local.addr.version) 266 return EINVAL; 267 268 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - encode pdu"); 269 270 rc = udp_pdu_encode(&epp, msg, &pdu); 272 rc = udp_pdu_encode(&sp, msg, &pdu); 271 273 if (rc != EOK) 272 274 return ENOMEM; 273 275 274 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - transmit");275 276 276 rc = udp_transmit_pdu(pdu); 277 277 udp_pdu_delete(pdu); … … 280 280 return EIO; 281 281 282 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - success");283 282 return EOK; 284 283 } … … 288 287 * Pull one message from the association's receive queue. 289 288 */ 290 int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, inet_ep_t *remote)289 int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, udp_sock_t *fsock) 291 290 { 292 291 link_t *link; … … 304 303 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - association was reset"); 305 304 fibril_mutex_unlock(&assoc->lock); 306 return E NXIO;305 return ECONNABORTED; 307 306 } 308 307 … … 314 313 315 314 *msg = rqe->msg; 316 * remote = rqe->epp.remote;315 *fsock = rqe->sp.foreign; 317 316 free(rqe); 318 317 … … 324 323 * Find the association to which the message belongs and queue it. 325 324 */ 326 void udp_assoc_received( inet_ep2_t *repp, udp_msg_t *msg)325 void udp_assoc_received(udp_sockpair_t *rsp, udp_msg_t *msg) 327 326 { 328 327 udp_assoc_t *assoc; 329 328 int rc; 330 329 331 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", r epp, msg);332 333 assoc = udp_assoc_find_ref(r epp);330 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg); 331 332 assoc = udp_assoc_find_ref(rsp); 334 333 if (assoc == NULL) { 335 334 log_msg(LOG_DEFAULT, LVL_DEBUG, "No association found. Message dropped."); … … 340 339 } 341 340 342 if (0) { 343 rc = udp_assoc_queue_msg(assoc, repp, msg); 344 if (rc != EOK) { 345 log_msg(LOG_DEFAULT, LVL_DEBUG, "Out of memory. Message dropped."); 341 rc = udp_assoc_queue_msg(assoc, rsp, msg); 342 if (rc != EOK) { 343 log_msg(LOG_DEFAULT, LVL_DEBUG, "Out of memory. Message dropped."); 346 344 /* XXX Generate ICMP error? */ 347 } 348 } 349 350 log_msg(LOG_DEFAULT, LVL_DEBUG, "call assoc->cb->recv_msg"); 351 assoc->cb->recv_msg(assoc->cb_arg, repp, msg); 352 udp_assoc_delref(assoc); 345 } 353 346 } 354 347 … … 366 359 } 367 360 368 static int udp_assoc_queue_msg(udp_assoc_t *assoc, inet_ep2_t *epp,361 static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp, 369 362 udp_msg_t *msg) 370 363 { … … 372 365 373 366 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)", 374 assoc, epp, msg);367 assoc, sp, msg); 375 368 376 369 rqe = calloc(1, sizeof(udp_rcv_queue_entry_t)); … … 379 372 380 373 link_initialize(&rqe->link); 381 rqe-> epp = *epp;374 rqe->sp = *sp; 382 375 rqe->msg = msg; 383 376 … … 391 384 } 392 385 393 /** Find association structure for specified endpoint pair. 394 * 395 * An association is uniquely identified by an endpoint pair. Look up our 396 * association map and return association structure based on endpoint pair. 386 /** Match socket with pattern. */ 387 static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt) 388 { 389 log_msg(LOG_DEFAULT, LVL_DEBUG, 390 "udp_socket_match(sock=(%u), pat=(%u))", sock->port, patt->port); 391 392 if ((!inet_addr_is_any(&patt->addr)) && 393 (!inet_addr_compare(&patt->addr, &sock->addr))) 394 return false; 395 396 if ((patt->port != UDP_PORT_ANY) && 397 (patt->port != sock->port)) 398 return false; 399 400 log_msg(LOG_DEFAULT, LVL_DEBUG, " -> match"); 401 402 return true; 403 } 404 405 /** Match socket pair with pattern. */ 406 static bool udp_sockpair_match(udp_sockpair_t *sp, udp_sockpair_t *pattern) 407 { 408 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern); 409 410 if (!udp_socket_match(&sp->local, &pattern->local)) 411 return false; 412 413 if (!udp_socket_match(&sp->foreign, &pattern->foreign)) 414 return false; 415 416 log_msg(LOG_DEFAULT, LVL_DEBUG, "Socket pair matched."); 417 return true; 418 } 419 420 421 /** Find association structure for specified socket pair. 422 * 423 * An association is uniquely identified by a socket pair. Look up our 424 * association map and return association structure based on socket pair. 397 425 * The association reference count is bumped by one. 398 426 * 399 * @param epp Endpoint pair427 * @param sp Socket pair 400 428 * @return Association structure or NULL if not found. 401 429 */ 402 static udp_assoc_t *udp_assoc_find_ref(inet_ep2_t *epp) 403 { 404 int rc; 405 void *arg; 406 udp_assoc_t *assoc; 407 408 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_find_ref(%p)", epp); 430 static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp) 431 { 432 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_find_ref(%p)", sp); 433 409 434 fibril_mutex_lock(&assoc_list_lock); 410 411 rc = amap_find_match(amap, epp, &arg); 412 if (rc != EOK) { 413 assert(rc == ENOMEM); 414 fibril_mutex_unlock(&assoc_list_lock); 415 return NULL; 416 } 417 418 assoc = (udp_assoc_t *)arg; 419 udp_assoc_addref(assoc); 420 435 436 list_foreach(assoc_list, link, udp_assoc_t, assoc) { 437 udp_sockpair_t *asp = &assoc->ident; 438 439 /* Skip unbound associations */ 440 if (asp->local.port == UDP_PORT_ANY) 441 continue; 442 443 if (udp_sockpair_match(sp, asp)) { 444 log_msg(LOG_DEFAULT, LVL_DEBUG, "Returning assoc %p", assoc); 445 udp_assoc_addref(assoc); 446 fibril_mutex_unlock(&assoc_list_lock); 447 return assoc; 448 } 449 } 450 421 451 fibril_mutex_unlock(&assoc_list_lock); 422 return assoc;452 return NULL; 423 453 } 424 454
Note:
See TracChangeset
for help on using the changeset viewer.