Changes in uspace/srv/net/udp/assoc.c [071a2c60:c3f7d37] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/udp/assoc.c
r071a2c60 rc3f7d37 1 1 /* 2 * Copyright (c) 201 2Jiri Svoboda2 * Copyright (c) 2015 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 36 36 37 37 #include <adt/list.h> 38 #include <errno.h> 38 39 #include <stdbool.h> 39 40 #include <fibril_synch.h> 41 #include <inet/endpoint.h> 40 42 #include <io/log.h> 43 #include <nettl/amap.h> 41 44 #include <stdlib.h> 42 45 … … 44 47 #include "msg.h" 45 48 #include "pdu.h" 46 #include "ucall.h"47 49 #include "udp_inet.h" 48 50 #include "udp_type.h" 49 51 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 *); 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 } 57 72 58 73 /** Create new association structure. 59 74 * 60 * @param lsock Local socket (will be deeply copied) 61 * @param fsock Foreign socket (will be deeply copied) 75 * @param epp Endpoint pair (will be copied) 76 * @param cb Callbacks 77 * @param cb_arg Callback argument 62 78 * @return New association or NULL 63 79 */ 64 udp_assoc_t *udp_assoc_new( udp_sock_t *lsock, udp_sock_t *fsock)80 udp_assoc_t *udp_assoc_new(inet_ep2_t *epp, udp_assoc_cb_t *cb, void *cb_arg) 65 81 { 66 82 udp_assoc_t *assoc = NULL; … … 80 96 fibril_condvar_initialize(&assoc->rcv_queue_cv); 81 97 82 if (lsock != NULL) 83 assoc->ident.local = *lsock; 84 85 if (fsock != NULL) 86 assoc->ident.foreign = *fsock; 87 98 if (epp != NULL) 99 assoc->ident = *epp; 100 101 assoc->cb = cb; 102 assoc->cb_arg = cb_arg; 88 103 return assoc; 89 104 error: … … 166 181 * Add association to the association map. 167 182 */ 168 void udp_assoc_add(udp_assoc_t *assoc) 169 { 183 int udp_assoc_add(udp_assoc_t *assoc) 184 { 185 inet_ep2_t aepp; 186 int rc; 187 170 188 udp_assoc_addref(assoc); 171 189 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; 172 199 list_append(&assoc->link, &assoc_list); 173 200 fibril_mutex_unlock(&assoc_list_lock); 201 202 return EOK; 174 203 } 175 204 … … 181 210 { 182 211 fibril_mutex_lock(&assoc_list_lock); 212 amap_remove(amap, &assoc->ident); 183 213 list_remove(&assoc->link); 184 214 fibril_mutex_unlock(&assoc_list_lock); … … 196 226 assoc, iplink); 197 227 fibril_mutex_lock(&assoc->lock); 198 assoc->ident. iplink = iplink;228 assoc->ident.local_link = iplink; 199 229 fibril_mutex_unlock(&assoc->lock); 200 230 } 201 231 202 /** Set foreign socket in association.203 *204 * @param assoc Association205 * @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 Association218 * @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 Association232 * @param lport Local port233 *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;240 fibril_mutex_unlock(&assoc->lock);241 }242 243 232 /** Send message to association. 244 233 * 245 234 * @param assoc Association 246 * @param fsock Foreign socket or NULL not to override @a assoc235 * @param remote Remote endpoint or NULL not to override @a assoc 247 236 * @param msg Message 248 237 * 249 238 * @return EOK on success 250 * EINVAL if foreign socket is not set239 * EINVAL if remote endpoint is not set 251 240 * ENOMEM if out of resources 252 241 * EIO if no route to destination exists 253 242 */ 254 int udp_assoc_send(udp_assoc_t *assoc, udp_sock_t *fsock, udp_msg_t *msg)243 int udp_assoc_send(udp_assoc_t *assoc, inet_ep_t *remote, udp_msg_t *msg) 255 244 { 256 245 udp_pdu_t *pdu; 257 udp_sockpair_t sp;246 inet_ep2_t epp; 258 247 int rc; 259 248 260 249 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send(%p, %p, %p)", 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)) 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)) 270 261 return EINVAL; 271 262 272 rc = udp_pdu_encode(&sp, msg, &pdu); 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); 273 271 if (rc != EOK) 274 272 return ENOMEM; 275 273 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"); 282 283 return EOK; 283 284 } … … 287 288 * Pull one message from the association's receive queue. 288 289 */ 289 int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, udp_sock_t *fsock)290 int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, inet_ep_t *remote) 290 291 { 291 292 link_t *link; … … 303 304 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - association was reset"); 304 305 fibril_mutex_unlock(&assoc->lock); 305 return E CONNABORTED;306 return ENXIO; 306 307 } 307 308 … … 313 314 314 315 *msg = rqe->msg; 315 * fsock = rqe->sp.foreign;316 *remote = rqe->epp.remote; 316 317 free(rqe); 317 318 … … 323 324 * Find the association to which the message belongs and queue it. 324 325 */ 325 void udp_assoc_received( udp_sockpair_t *rsp, udp_msg_t *msg)326 void udp_assoc_received(inet_ep2_t *repp, udp_msg_t *msg) 326 327 { 327 328 udp_assoc_t *assoc; 328 329 int rc; 329 330 330 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", r sp, msg);331 332 assoc = udp_assoc_find_ref(r sp);331 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", repp, msg); 332 333 assoc = udp_assoc_find_ref(repp); 333 334 if (assoc == NULL) { 334 335 log_msg(LOG_DEFAULT, LVL_DEBUG, "No association found. Message dropped."); … … 339 340 } 340 341 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."); 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."); 344 346 /* XXX Generate ICMP error? */ 345 } 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); 346 353 } 347 354 … … 359 366 } 360 367 361 static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp,368 static int udp_assoc_queue_msg(udp_assoc_t *assoc, inet_ep2_t *epp, 362 369 udp_msg_t *msg) 363 370 { … … 365 372 366 373 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)", 367 assoc, sp, msg);374 assoc, epp, msg); 368 375 369 376 rqe = calloc(1, sizeof(udp_rcv_queue_entry_t)); … … 372 379 373 380 link_initialize(&rqe->link); 374 rqe-> sp = *sp;381 rqe->epp = *epp; 375 382 rqe->msg = msg; 376 383 … … 384 391 } 385 392 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. 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. 425 397 * The association reference count is bumped by one. 426 398 * 427 * @param sp Socket pair399 * @param epp Endpoint pair 428 400 * @return Association structure or NULL if not found. 429 401 */ 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 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); 434 409 fibril_mutex_lock(&assoc_list_lock); 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 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 451 421 fibril_mutex_unlock(&assoc_list_lock); 452 return NULL;422 return assoc; 453 423 } 454 424
Note:
See TracChangeset
for help on using the changeset viewer.