Navigation


Changeset 85:e5fcd672caff in freeDiameter


Ignore:
Timestamp:
Dec 3, 2009, 2:59:23 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Added new function to retrieve messages sessions easily

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/routing.c

    r82 r85  
    5252        return ENOTSUP;
    5353}
     54
     55int 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 );
     56int fd_rt_fwd_unregister ( struct fd_rt_fwd_hdl * handler, void ** cbdata );
     57
     58int 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 );
     59int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata );
  • include/freeDiameter/freeDiameter.h

    r83 r85  
    445445 *   - routable messages are queued in the fd_g_incoming global queue.
    446446 *   - 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).
    448448 *   - If the message is handled locally, it is queued in fd_g_local.
    449449 *   - Another thread (dispatch.c) will handle this message and pass it to registered callbacks (see fd_disp_register in libfreeDiameter.h).
     
    451451 * (*) FWD messages details:
    452452 *   - 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.
    453454 *   - All callbacks registered with fd_rt_fwd_register are called for the message (see bellow).
    454455 *     - these callbacks will typically do proxying work. Note that adding the route-record is handled by the daemon.
     
    457458 *
    458459 * (*) 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:
    462462 *      - create a list of all known peers in the "OPEN" state.
    463463 *      - remove from that list all peers that are in a Route-Record AVP of the message, to avoid routing loops.
    464464 *      - 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.
    466466 *   - Otherwise, call all callbacks registered by function fd_rt_out_register, with the list of peers and the message.
    467467 *   - Order the resulting list of peers by score (see bellow), and sent the message to the peer with highest (positive) score.
    468468 *    - in case the peer is no longer in the "OPEN" state, send the message to the second peer in the list.
    469469 *      - 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 */
     478struct fd_rt_fwd_hdl;
     479
     480/* Message direction for the callback */
     481enum 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 */
     505int 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 */
     537int 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 */
     543struct fd_rt_out_hdl;
     544
     545enum 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 */
     577int 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 */
     612int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata );
    476613
    477614
  • include/freeDiameter/libfreeDiameter.h

    r83 r85  
    14731473 *
    14741474 * 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
    14771476 *  id, a new object is silently created (equivalent to fd_sess_new with flag SESSION_NEW_FULL).
    14781477 *
     
    16481647int  fd_rtd_candidate_reorder(struct fd_list * candidates);
    16491648
     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 */
    16501651
    16511652/*============================================================*/
     
    20522053
    20532054
     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 */
     2073int fd_msg_sess_get(struct dictionary * dict, struct msg * msg, struct session ** session, int * new);
     2074
    20542075/***************************************/
    20552076/*   Manage AVP values                 */
  • libfreeDiameter/libfD.h

    r14 r85  
    5656extern pthread_rwlock_t fd_disp_lock;
    5757
     58/* Messages / sessions API */
     59int fd_sess_fromsid_msg ( unsigned char * sid, size_t len, struct session ** session, int * new);
     60int fd_sess_reclaim_msg ( struct session ** session );
     61
    5862#endif /* _LIBFD_H */
  • libfreeDiameter/messages.c

    r83 r85  
    119119        struct msg              *msg_query;             /* the associated query if the message is a received answer */
    120120        struct rt_data          *msg_rtdata;            /* Routing list for the query */
     121        struct session          *msg_sess;              /* Cached message session if any */
    121122        struct {
    122123                        void (*fct)(void *, struct msg **);
     
    573574        }
    574575       
     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       
    575580        /* free the object */
    576581        free(obj);
     
    661666                msg->msg_public.msg_eteid
    662667                );
    663         fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p src:%s\n",
    664                         INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_src_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)");
    665670}
    666671
     
    11291134}
    11301135
     1136/* Retrieve the session of the message */
     1137int 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
    11311187/******************* End-to-end counter *********************/
    11321188uint32_t fd_eteid;
  • libfreeDiameter/sessions.c

    r14 r85  
    100100        pthread_mutex_t stlock; /* A lock to protect the list of states associated with this session */
    101101        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 */
    102103};
    103104
     
    675676}
    676677
     678/* For the messages module */
     679int 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
     696int 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
    677718
    678719/* Dump functions */
Note: See TracChangeset for help on using the changeset viewer.