Changeset 85:e5fcd672caff in freeDiameter
- Timestamp:
- Dec 3, 2009, 2:59:23 PM (14 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/routing.c
r82 r85 52 52 return ENOTSUP; 53 53 } 54 55 int fd_rt_fwd_register ( int (*rt_fwd_cb)(void * cbdata, struct msg ** msg), void * cbdata, enum fd_rt_fwd_dir dir, struct fd_rt_fwd_hdl ** handler ); 56 int fd_rt_fwd_unregister ( struct fd_rt_fwd_hdl * handler, void ** cbdata ); 57 58 int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg * msg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler ); 59 int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata ); -
include/freeDiameter/freeDiameter.h
r83 r85 445 445 * - routable messages are queued in the fd_g_incoming global queue. 446 446 * - a thread (routing-in) picks the message and takes the decision if it is handled locally or forwarded, 447 * based on local capabilities (registered by extensions ).447 * based on local capabilities (registered by extensions with fd_disp_app_support). 448 448 * - If the message is handled locally, it is queued in fd_g_local. 449 449 * - Another thread (dispatch.c) will handle this message and pass it to registered callbacks (see fd_disp_register in libfreeDiameter.h). … … 451 451 * (*) FWD messages details: 452 452 * - The process is the same as for IN messages, until the routing-in threads makes its decision that the message is not handled locally. 453 * - If the local peer does not relay message, an error DIAMETER_APPLICATION_UNSUPPORTED is returned. 453 454 * - All callbacks registered with fd_rt_fwd_register are called for the message (see bellow). 454 455 * - these callbacks will typically do proxying work. Note that adding the route-record is handled by the daemon. … … 457 458 * 458 459 * (*) OUT messages details: 459 * - The message are picked from fd_g_outgoing, as result of forwarding process or call to fd_msg_send. 460 * - The (routing-out) thread builds a list of possible destinations for the message. 461 * The logic to build this list is as follow: 460 * - The message are picked from fd_g_outgoing (they are queued there as result of forwarding process or call to fd_msg_send.) 461 * - The (routing-out) thread builds a list of possible destinations for the message, as follow: 462 462 * - create a list of all known peers in the "OPEN" state. 463 463 * - remove from that list all peers that are in a Route-Record AVP of the message, to avoid routing loops. 464 464 * - remove also all peers that have previously replied an error message for this message. 465 * - If the list is empty, create an error UNABLE_TO_DELIVER (note: should we trig dynamic discovery here???) and reply this.465 * - If the list is empty, create an error UNABLE_TO_DELIVER (note: should we trig dynamic discovery here???) and reply. 466 466 * - Otherwise, call all callbacks registered by function fd_rt_out_register, with the list of peers and the message. 467 467 * - Order the resulting list of peers by score (see bellow), and sent the message to the peer with highest (positive) score. 468 468 * - in case the peer is no longer in the "OPEN" state, send the message to the second peer in the list. 469 469 * - if no peer is in OPEN state anymore, restart the process of creating the list. 470 * - The peer thread will handle the creation of the Hop-by-hop ID and sending the message. 471 * 472 * This part of the API (routing-api.h) provides the definitions of the rt_out_cb_t and rt_fwd_cb_t callbacks, and the 473 * functions to register and deregister these callbacks. 474 */ 475 470 * - Once a peer has been selected, the message is queued into that peer's outgoing queue. 471 * 472 * The following functions allow an extension to register or remove a callback as described above. 473 */ 474 475 /********** Forwarding callbacks: for Proxy operations ***********/ 476 477 /* Handle to registered callback */ 478 struct fd_rt_fwd_hdl; 479 480 /* Message direction for the callback */ 481 enum fd_rt_fwd_dir { 482 RT_FWD_REQ = 1, /* The callback will be called on forwarded requests only */ 483 RT_FWD_ANS, /* The callback will be called on answers and errors only */ 484 RT_FWD_ALL, /* The callback will be called on all forwarded messages */ 485 }; 486 487 /* 488 * FUNCTION: fd_rt_fwd_register 489 * 490 * PARAMETERS: 491 * rt_fwd_cb : The callback function to register (see prototype bellow). 492 * cbdata : Pointer to pass to the callback when it is called. The data is opaque to the daemon. 493 * dir : One of the RT_FWD_* directions defined above. 494 * handler : On success, a handler to the registered callback is stored here. 495 * This handler will be used to unregister the cb. 496 * 497 * DESCRIPTION: 498 * Register a new callback for forwarded messages. See explanations above. 499 * 500 * RETURN VALUE: 501 * 0 : The callback is registered. 502 * EINVAL : A parameter is invalid. 503 * ENOMEM : Not enough memory to complete the operation 504 */ 505 int fd_rt_fwd_register ( int (*rt_fwd_cb)(void * cbdata, struct msg ** msg), void * cbdata, enum fd_rt_fwd_dir dir, struct fd_rt_fwd_hdl ** handler ); 506 /* 507 * CALLBACK: rt_fwd_cb 508 * 509 * PARAMETERS: 510 * data : pointer to some data that was passed when the callback was registered (optional). 511 * msg : The message that is being forwarded. 512 * 513 * DESCRIPTION: 514 * This callback is called when a message is forwarded to another peer. It may for example add a Proxy-Info AVP. 515 * The callback may also choose to handle the message in a more complex form. In that case, it must set *msg = NULL 516 * and handle it differently. In such case, the forwarding thread will stop processing this message. 517 * 518 * RETURN VALUE: 519 * 0 : Operation complete. 520 * !0 : An error occurred -- will result in daemon's termination. 521 */ 522 523 /* 524 * FUNCTION: fd_rt_fwd_unregister 525 * 526 * PARAMETERS: 527 * handler : The handler of the callback that must be unregistered. 528 * cbdata : Will receive the data registered with the callback, that can be freed if needed. 529 * 530 * DESCRIPTION: 531 * Removes a callback from the list of registered callbacks. 532 * 533 * RETURN VALUE: 534 * 0 : The callback is unregistered. 535 * EINVAL : A parameter is invalid. 536 */ 537 int fd_rt_fwd_unregister ( struct fd_rt_fwd_hdl * handler, void ** cbdata ); 538 539 540 /********** Out callbacks: for next hop routing decision operations ***********/ 541 542 /* Handle to registered callback */ 543 struct fd_rt_out_hdl; 544 545 enum fd_rt_out_score { 546 FD_SCORE_NO_DELIVERY = -70, /* We should not send this message to this candidate */ 547 FD_SCORE_LOAD_BALANCE = 1, /* Use this to differentiate between several peers with the same score */ 548 FD_SCORE_DEFAULT = 5, /* The peer is a default route for all messages */ 549 FD_SCORE_DEFAULT_REALM = 10, /* The peer is a default route for this realm */ 550 FD_SCORE_REDIR_HOST = 25, /* If there is a redirect rule with ALL_HOST for these message and peer */ 551 FD_SCORE_REDIR_APP = 30, /* If there is a redirect rule with ALL_APPLICATION for these message and peer */ 552 FD_SCORE_REDIR_REALM = 35, /* If there is a redirect rule with ALL_REALM for these message and peer */ 553 FD_SCORE_REDIR_REALM_APP = 40, /* If there is a redirect rule with REALM_AND_APPLICATION for these message and peer */ 554 FD_SCORE_REDIR_USER = 45, /* If there is a redirect rule with ALL_USER for these message and peer */ 555 FD_SCORE_REDIR_SESSION = 50, /* If there is a redirect rule with ALL_SESSION for these message and peer */ 556 FD_SCORE_FINALDEST = 100 /* If the peer is the final recipient of the message, it receives a big score. */ 557 }; 558 559 /* 560 * FUNCTION: fd_rt_out_register 561 * 562 * PARAMETERS: 563 * rt_out_cb : The callback function to register (see prototype bellow). 564 * cbdata : Pointer to pass to the callback when it is called. The data is opaque to the daemon. 565 * priority : Order for calling this callback. The callbacks are called in reverse priority order (higher priority = called sooner). 566 * handler : On success, a handler to the registered callback is stored here. 567 * This handler will be used to unregister the cb. 568 * 569 * DESCRIPTION: 570 * Register a new callback to handle OUT routing decisions. See explanations above. 571 * 572 * RETURN VALUE: 573 * 0 : The callback is registered. 574 * EINVAL : A parameter is invalid. 575 * ENOMEM : Not enough memory to complete the operation 576 */ 577 int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg * msg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler ); 578 /* 579 * CALLBACK: rt_out_cb 580 * 581 * PARAMETERS: 582 * cbdata : pointer to some data that was registered with the callback. 583 * msg : The message that must be sent. 584 * list : The list of peers to which the message may be sent to, as returned by fd_rtd_candidate_extract 585 * 586 * DESCRIPTION: 587 * This callback must attribute a score (preferably from FD_SCORE_*) to each candidate peer in the list. 588 * Once all registered callbacks have been called, the message is sent to the candidate with the highest score. 589 * Note that each callback must *add* its locally-attributed score to the candidate current "score" parameter, not replace it! 590 * Note also that this callback must be re-entrant since it may be called by several threads at the same time 591 * (for different messages) 592 * 593 * RETURN VALUE: 594 * 0 : Operation complete. 595 * !0 : An error occurred. 596 */ 597 598 /* 599 * FUNCTION: fd_rt_out_unregister 600 * 601 * PARAMETERS: 602 * handler : The handler of the callback that must be unregistered. 603 * cbdata : Will receive the data registered with the callback, that can be freed if needed. 604 * 605 * DESCRIPTION: 606 * Removes a callback from the list of registered callbacks. 607 * 608 * RETURN VALUE: 609 * 0 : The callback is unregistered. 610 * EINVAL : A parameter is invalid. 611 */ 612 int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata ); 476 613 477 614 -
include/freeDiameter/libfreeDiameter.h
r83 r85 1473 1473 * 1474 1474 * DESCRIPTION: 1475 * Retrieve a session object from a Session-Id string. Calling this function makes an implicit call to the 1476 * fd_sess_link function on the returned session. In case no session object was previously existing with this 1475 * Retrieve a session object from a Session-Id string. In case no session object was previously existing with this 1477 1476 * id, a new object is silently created (equivalent to fd_sess_new with flag SESSION_NEW_FULL). 1478 1477 * … … 1648 1647 int fd_rtd_candidate_reorder(struct fd_list * candidates); 1649 1648 1649 /* Note : it is fine for a callback to add a new entry in the candidates list after the list has been extracted. The diamid must then be malloc'd. */ 1650 /* Beware that this could lead to routing loops */ 1650 1651 1651 1652 /*============================================================*/ … … 2052 2053 2053 2054 2055 /* 2056 * FUNCTION: fd_msg_sess_get 2057 * 2058 * PARAMETERS: 2059 * dict : the dictionary that contains the Session-Id AVP definition 2060 * msg : A valid message. 2061 * session : Location to store the session pointer when retrieved. 2062 * new : Indicates if the session has been created. 2063 * 2064 * DESCRIPTION: 2065 * This function retrieves or creates the session object corresponding to a message. 2066 * If the message does not contain a Session-Id AVP, *session == NULL on return. 2067 * Note that the Session-Id AVP must never be modified after created in a message. 2068 * 2069 * RETURN VALUE: 2070 * 0 : success 2071 * !0 : standard error code. 2072 */ 2073 int fd_msg_sess_get(struct dictionary * dict, struct msg * msg, struct session ** session, int * new); 2074 2054 2075 /***************************************/ 2055 2076 /* Manage AVP values */ -
libfreeDiameter/libfD.h
r14 r85 56 56 extern pthread_rwlock_t fd_disp_lock; 57 57 58 /* Messages / sessions API */ 59 int fd_sess_fromsid_msg ( unsigned char * sid, size_t len, struct session ** session, int * new); 60 int fd_sess_reclaim_msg ( struct session ** session ); 61 58 62 #endif /* _LIBFD_H */ -
libfreeDiameter/messages.c
r83 r85 119 119 struct msg *msg_query; /* the associated query if the message is a received answer */ 120 120 struct rt_data *msg_rtdata; /* Routing list for the query */ 121 struct session *msg_sess; /* Cached message session if any */ 121 122 struct { 122 123 void (*fct)(void *, struct msg **); … … 573 574 } 574 575 576 if ((obj->type == MSG_MSG) && (_M(obj)->msg_sess != NULL)) { 577 CHECK_FCT_DO( fd_sess_reclaim_msg ( &_M(obj)->msg_sess ), /* continue */); 578 } 579 575 580 /* free the object */ 576 581 free(obj); … … 661 666 msg->msg_public.msg_eteid 662 667 ); 663 fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p s rc:%s\n",664 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_s rc_id?:"(nil)");668 fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p sess:%p src:%s\n", 669 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_sess, msg->msg_src_id?:"(nil)"); 665 670 } 666 671 … … 1129 1134 } 1130 1135 1136 /* Retrieve the session of the message */ 1137 int fd_msg_sess_get(struct dictionary * dict, struct msg * msg, struct session ** session, int * new) 1138 { 1139 struct avp * avp; 1140 1141 TRACE_ENTRY("%p %p %p", msg, session, new); 1142 1143 /* Check we received valid parameters */ 1144 CHECK_PARAMS( CHECK_MSG(msg) ); 1145 CHECK_PARAMS( session ); 1146 1147 /* If we already resolved the session, just send it back */ 1148 if (msg->msg_sess) { 1149 *session = msg->msg_sess; 1150 if (new) 1151 *new = 0; 1152 return 0; 1153 } 1154 1155 /* OK, we have to search for Session-Id AVP -- it is usually the first AVP, but let's be permissive here */ 1156 /* -- note: we accept messages that have not yet been dictionary parsed... */ 1157 CHECK_FCT( fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, &avp, NULL) ); 1158 while (avp) { 1159 if ( (avp->avp_public.avp_code == AC_SESSION_ID) 1160 && (avp->avp_public.avp_vendor == 0) ) 1161 break; 1162 1163 /* Otherwise move to next AVP in the message */ 1164 CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) ); 1165 } 1166 1167 if (!avp) { 1168 TRACE_DEBUG(FULL, "No Session-Id AVP found in message %p", msg); 1169 *session = NULL; 1170 return 0; 1171 } 1172 1173 if (!avp->avp_model) { 1174 CHECK_FCT( fd_msg_parse_dict ( avp, dict ) ); 1175 } 1176 1177 ASSERT( avp->avp_public.avp_value ); 1178 1179 /* Resolve the session and we are done */ 1180 CHECK_FCT( fd_sess_fromsid_msg ( avp->avp_public.avp_value->os.data, avp->avp_public.avp_value->os.len, &msg->msg_sess, new) ); 1181 *session = msg->msg_sess; 1182 1183 return 0; 1184 } 1185 1186 1131 1187 /******************* End-to-end counter *********************/ 1132 1188 uint32_t fd_eteid; -
libfreeDiameter/sessions.c
r14 r85 100 100 pthread_mutex_t stlock; /* A lock to protect the list of states associated with this session */ 101 101 struct fd_list states; /* Sentinel for the list of states of this session. */ 102 int msg_cnt;/* Reference counter for the messages pointing to this session */ 102 103 }; 103 104 … … 675 676 } 676 677 678 /* For the messages module */ 679 int fd_sess_fromsid_msg ( unsigned char * sid, size_t len, struct session ** session, int * new) 680 { 681 TRACE_ENTRY("%p %zd %p %p", sid, len, session, new); 682 CHECK_PARAMS( sid && len && session && VALIDATE_SI(*session) ); 683 684 /* Get the session object */ 685 CHECK_FCT( fd_sess_fromsid ( (char *) sid, len, session, new) ); 686 687 /* Update the msg refcount */ 688 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); 689 (*session)->msg_cnt++; 690 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); 691 692 /* Done */ 693 return 0; 694 } 695 696 int fd_sess_reclaim_msg ( struct session ** session ) 697 { 698 int reclaim; 699 700 TRACE_ENTRY("%p", session); 701 CHECK_PARAMS( session && VALIDATE_SI(*session) ); 702 703 /* Update the msg refcount */ 704 CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); 705 reclaim = (*session)->msg_cnt; 706 (*session)->msg_cnt = reclaim - 1; 707 CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); 708 709 if (reclaim == 1) { 710 CHECK_FCT(fd_sess_reclaim ( session )); 711 } else { 712 *session = NULL; 713 } 714 return 0; 715 } 716 717 677 718 678 719 /* Dump functions */
Note: See TracChangeset
for help on using the changeset viewer.