Changes in uspace/srv/net/udp/assoc.c [443a0bc:c0f3460] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/udp/assoc.c
r443a0bc rc0f3460 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); … … 216 186 } 217 187 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); 227 fibril_mutex_lock(&assoc->lock); 228 assoc->ident.local_link = iplink; 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); 196 fibril_mutex_lock(&assoc->lock); 197 assoc->ident.foreign = *fsock; 198 fibril_mutex_unlock(&assoc->lock); 199 } 200 201 /** Set local socket in association. 202 * 203 * @param assoc Association 204 * @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 Association 218 * @param lport Local port 219 * 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; 229 226 fibril_mutex_unlock(&assoc->lock); 230 227 } … … 233 230 * 234 231 * @param assoc Association 235 * @param remote Remote endpoint or NULL not to override @a assoc232 * @param fsock Foreign socket or NULL not to override @a assoc 236 233 * @param msg Message 237 234 * 238 235 * @return EOK on success 239 * EINVAL if remote endpoint is not set236 * EINVAL if foreign socket is not set 240 237 * ENOMEM if out of resources 241 238 * EIO if no route to destination exists 242 239 */ 243 int udp_assoc_send(udp_assoc_t *assoc, inet_ep_t *remote, udp_msg_t *msg)240 int udp_assoc_send(udp_assoc_t *assoc, udp_sock_t *fsock, udp_msg_t *msg) 244 241 { 245 242 udp_pdu_t *pdu; 246 inet_ep2_t epp;243 udp_sockpair_t sp; 247 244 int rc; 248 245 249 246 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)) 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)) 261 256 return EINVAL; 262 257 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); 258 rc = udp_pdu_encode(&sp, msg, &pdu); 271 259 if (rc != EOK) 272 260 return ENOMEM; 273 261 274 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - transmit");275 276 262 rc = udp_transmit_pdu(pdu); 277 udp_pdu_delete(pdu);278 279 263 if (rc != EOK) 280 264 return EIO; 281 265 282 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send - success"); 266 udp_pdu_delete(pdu); 267 283 268 return EOK; 284 269 } … … 288 273 * Pull one message from the association's receive queue. 289 274 */ 290 int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, inet_ep_t *remote)275 int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, udp_sock_t *fsock) 291 276 { 292 277 link_t *link; … … 304 289 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - association was reset"); 305 290 fibril_mutex_unlock(&assoc->lock); 306 return E NXIO;291 return ECONNABORTED; 307 292 } 308 293 … … 314 299 315 300 *msg = rqe->msg; 316 * remote = rqe->epp.remote;301 *fsock = rqe->sp.foreign; 317 302 free(rqe); 318 303 … … 324 309 * Find the association to which the message belongs and queue it. 325 310 */ 326 void udp_assoc_received( inet_ep2_t *repp, udp_msg_t *msg)311 void udp_assoc_received(udp_sockpair_t *rsp, udp_msg_t *msg) 327 312 { 328 313 udp_assoc_t *assoc; 329 314 int rc; 330 315 331 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", r epp, msg);332 333 assoc = udp_assoc_find_ref(r epp);316 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg); 317 318 assoc = udp_assoc_find_ref(rsp); 334 319 if (assoc == NULL) { 335 320 log_msg(LOG_DEFAULT, LVL_DEBUG, "No association found. Message dropped."); 336 321 /* XXX Generate ICMP error. */ 337 322 /* XXX Might propagate error directly by error return. */ 338 udp_msg_delete(msg);339 323 return; 340 324 } 341 325 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."); 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."); 346 329 /* 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); 330 } 353 331 } 354 332 … … 366 344 } 367 345 368 static int udp_assoc_queue_msg(udp_assoc_t *assoc, inet_ep2_t *epp,346 static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp, 369 347 udp_msg_t *msg) 370 348 { … … 372 350 373 351 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)", 374 assoc, epp, msg);352 assoc, sp, msg); 375 353 376 354 rqe = calloc(1, sizeof(udp_rcv_queue_entry_t)); … … 379 357 380 358 link_initialize(&rqe->link); 381 rqe-> epp = *epp;359 rqe->sp = *sp; 382 360 rqe->msg = msg; 383 361 … … 391 369 } 392 370 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. 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. 397 410 * The association reference count is bumped by one. 398 411 * 399 * @param epp Endpoint pair412 * @param sp Socket pair 400 413 * @return Association structure or NULL if not found. 401 414 */ 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); 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 409 419 fibril_mutex_lock(&assoc_list_lock); 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 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 421 437 fibril_mutex_unlock(&assoc_list_lock); 422 return assoc;438 return NULL; 423 439 } 424 440
Note:
See TracChangeset
for help on using the changeset viewer.