Changes in uspace/srv/net/udp/assoc.c [c0f3460:443a0bc] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/udp/assoc.c
rc0f3460 r443a0bc 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); … … 186 216 } 187 217 188 /** Set foreign socket in association. 189 * 190 * @param assoc Association 191 * @param fsock Foreign socket (deeply copied) 192 */ 193 void udp_assoc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock) 194 { 195 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock); 218 /** Set IP link in association. 219 * 220 * @param assoc Association 221 * @param iplink IP link 222 */ 223 void udp_assoc_set_iplink(udp_assoc_t *assoc, service_id_t iplink) 224 { 225 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_iplink(%p, %zu)", 226 assoc, iplink); 196 227 fibril_mutex_lock(&assoc->lock); 197 assoc->ident. foreign = *fsock;228 assoc->ident.local_link = iplink; 198 229 fibril_mutex_unlock(&assoc->lock); 199 230 } 200 231 201 /** Set local socket in association.202 *203 * @param assoc Association204 * @param lsock Local socket (deeply copied)205 *206 */207 void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)208 {209 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);210 fibril_mutex_lock(&assoc->lock);211 assoc->ident.local = *lsock;212 fibril_mutex_unlock(&assoc->lock);213 }214 215 /** Set local port in association.216 *217 * @param assoc Association218 * @param lport Local port219 *220 */221 void udp_assoc_set_local_port(udp_assoc_t *assoc, uint16_t lport)222 {223 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %" PRIu16 ")", assoc, lport);224 fibril_mutex_lock(&assoc->lock);225 assoc->ident.local.port = lport;226 fibril_mutex_unlock(&assoc->lock);227 }228 229 232 /** Send message to association. 230 233 * 231 234 * @param assoc Association 232 * @param fsock Foreign socket or NULL not to override @a assoc235 * @param remote Remote endpoint or NULL not to override @a assoc 233 236 * @param msg Message 234 237 * 235 238 * @return EOK on success 236 * EINVAL if foreign socket is not set239 * EINVAL if remote endpoint is not set 237 240 * ENOMEM if out of resources 238 241 * EIO if no route to destination exists 239 242 */ 240 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) 241 244 { 242 245 udp_pdu_t *pdu; 243 udp_sockpair_t sp;246 inet_ep2_t epp; 244 247 int rc; 245 248 246 249 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send(%p, %p, %p)", 247 assoc, fsock, msg); 248 249 /* @a fsock can be used to override the foreign socket */ 250 sp = assoc->ident; 251 if (fsock != NULL) 252 sp.foreign = *fsock; 253 254 if ((inet_addr_is_any(&sp.foreign.addr)) || 255 (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)) 256 261 return EINVAL; 257 262 258 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); 259 271 if (rc != EOK) 260 272 return ENOMEM; 261 273 274 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - transmit"); 275 262 276 rc = udp_transmit_pdu(pdu); 277 udp_pdu_delete(pdu); 278 263 279 if (rc != EOK) 264 280 return EIO; 265 281 266 udp_pdu_delete(pdu); 267 282 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - success"); 268 283 return EOK; 269 284 } … … 273 288 * Pull one message from the association's receive queue. 274 289 */ 275 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) 276 291 { 277 292 link_t *link; … … 289 304 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - association was reset"); 290 305 fibril_mutex_unlock(&assoc->lock); 291 return E CONNABORTED;306 return ENXIO; 292 307 } 293 308 … … 299 314 300 315 *msg = rqe->msg; 301 * fsock = rqe->sp.foreign;316 *remote = rqe->epp.remote; 302 317 free(rqe); 303 318 … … 309 324 * Find the association to which the message belongs and queue it. 310 325 */ 311 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) 312 327 { 313 328 udp_assoc_t *assoc; 314 329 int rc; 315 330 316 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", r sp, msg);317 318 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); 319 334 if (assoc == NULL) { 320 335 log_msg(LOG_DEFAULT, LVL_DEBUG, "No association found. Message dropped."); 321 336 /* XXX Generate ICMP error. */ 322 337 /* XXX Might propagate error directly by error return. */ 338 udp_msg_delete(msg); 323 339 return; 324 340 } 325 341 326 rc = udp_assoc_queue_msg(assoc, rsp, msg); 327 if (rc != EOK) { 328 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."); 329 346 /* XXX Generate ICMP error? */ 330 } 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); 331 353 } 332 354 … … 344 366 } 345 367 346 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, 347 369 udp_msg_t *msg) 348 370 { … … 350 372 351 373 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)", 352 assoc, sp, msg);374 assoc, epp, msg); 353 375 354 376 rqe = calloc(1, sizeof(udp_rcv_queue_entry_t)); … … 357 379 358 380 link_initialize(&rqe->link); 359 rqe-> sp = *sp;381 rqe->epp = *epp; 360 382 rqe->msg = msg; 361 383 … … 369 391 } 370 392 371 /** Match socket with pattern. */ 372 static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt) 373 { 374 log_msg(LOG_DEFAULT, LVL_DEBUG, 375 "udp_socket_match(sock=(%u), pat=(%u))", sock->port, patt->port); 376 377 if ((!inet_addr_is_any(&patt->addr)) && 378 (!inet_addr_compare(&patt->addr, &sock->addr))) 379 return false; 380 381 if ((patt->port != UDP_PORT_ANY) && 382 (patt->port != sock->port)) 383 return false; 384 385 log_msg(LOG_DEFAULT, LVL_DEBUG, " -> match"); 386 387 return true; 388 } 389 390 /** Match socket pair with pattern. */ 391 static bool udp_sockpair_match(udp_sockpair_t *sp, udp_sockpair_t *pattern) 392 { 393 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern); 394 395 if (!udp_socket_match(&sp->local, &pattern->local)) 396 return false; 397 398 if (!udp_socket_match(&sp->foreign, &pattern->foreign)) 399 return false; 400 401 log_msg(LOG_DEFAULT, LVL_DEBUG, "Socket pair matched."); 402 return true; 403 } 404 405 406 /** Find association structure for specified socket pair. 407 * 408 * An association is uniquely identified by a socket pair. Look up our 409 * 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. 410 397 * The association reference count is bumped by one. 411 398 * 412 * @param sp Socket pair399 * @param epp Endpoint pair 413 400 * @return Association structure or NULL if not found. 414 401 */ 415 static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp) 416 { 417 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_find_ref(%p)", sp); 418 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); 419 409 fibril_mutex_lock(&assoc_list_lock); 420 421 list_foreach(assoc_list, link) { 422 udp_assoc_t *assoc = list_get_instance(link, udp_assoc_t, link); 423 udp_sockpair_t *asp = &assoc->ident; 424 425 /* Skip unbound associations */ 426 if (asp->local.port == UDP_PORT_ANY) 427 continue; 428 429 if (udp_sockpair_match(sp, asp)) { 430 log_msg(LOG_DEFAULT, LVL_DEBUG, "Returning assoc %p", assoc); 431 udp_assoc_addref(assoc); 432 fibril_mutex_unlock(&assoc_list_lock); 433 return assoc; 434 } 435 } 436 410 411 rc = amap_find_match(amap, epp, &arg); 412 if (rc != EOK) { 413 assert(rc == ENOENT); 414 fibril_mutex_unlock(&assoc_list_lock); 415 return NULL; 416 } 417 418 assoc = (udp_assoc_t *)arg; 419 udp_assoc_addref(assoc); 420 437 421 fibril_mutex_unlock(&assoc_list_lock); 438 return NULL;422 return assoc; 439 423 } 440 424
Note:
See TracChangeset
for help on using the changeset viewer.