Navigation


Changeset 86:e3e22d89e023 in freeDiameter


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

Started routing module

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/peers.c

    r78 r86  
    159159}
    160160
     161/* Search for a peer */
     162int fd_peer_getbyid( char * diamid, struct peer_hdr ** peer )
     163{
     164        struct fd_list * li;
     165       
     166        TRACE_ENTRY("%p %p", diamid, peer);
     167        CHECK_PARAMS( diamid && peer );
     168       
     169        *peer = NULL;
     170       
     171        /* Search in the list */
     172        CHECK_POSIX( pthread_rwlock_rdlock(&fd_g_peers_rw) );
     173        for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     174                struct fd_peer * next = (struct fd_peer *)li;
     175                int cmp = strcasecmp( diamid, next->p_hdr.info.pi_diamid );
     176                if (cmp > 0)
     177                        continue;
     178                if (cmp == 0)
     179                        *peer = &next->p_hdr;
     180                break;
     181        }
     182        CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
     183       
     184        return 0;
     185}
     186
    161187
    162188#define free_null( _v )         \
  • freeDiameter/routing.c

    r85 r86  
    3636#include "fD.h"
    3737
     38/********************************************************************************/
     39/*              First part : handling the extensions callbacks                  */
     40/********************************************************************************/
     41
     42/* Lists of the callbacks, and locks to protect them */
     43static pthread_rwlock_t rt_fwd_lock = PTHREAD_RWLOCK_INITIALIZER;
     44static struct fd_list   rt_fwd_list = FD_LIST_INITIALIZER_O(rt_fwd_list, &rt_fwd_lock);
     45
     46static pthread_rwlock_t rt_out_lock = PTHREAD_RWLOCK_INITIALIZER;
     47static struct fd_list   rt_out_list = FD_LIST_INITIALIZER_O(rt_out_list, &rt_out_lock);
     48
     49/* Items in the lists are the same */
     50struct rt_hdl {
     51        struct fd_list  chain;  /* link in the rt_fwd_list or rt_out_list */
     52        void *          cbdata; /* the registered data */
     53        union {
     54                int     order;  /* This value is used to sort the list */
     55                int     dir;    /* It is the direction for FWD handlers */
     56                int     prio;   /* and the priority for OUT handlers */
     57        };
     58        union {
     59                int (*rt_fwd_cb)(void * cbdata, struct msg ** msg);
     60                int (*rt_out_cb)(void * cbdata, struct msg * msg, struct fd_list * candidates);
     61        };
     62};     
     63
     64/* Add a new entry in the list */
     65static int add_ordered(struct rt_hdl * new, struct fd_list * list)
     66{
     67        /* The list is ordered by prio parameter */
     68        struct fd_list * li;
     69       
     70        CHECK_POSIX( pthread_rwlock_wrlock(list->o) );
     71       
     72        for (li = list->next; li != list; li = li->next) {
     73                struct rt_hdl * h = (struct rt_hdl *) li;
     74                if (new->order <= h->order)
     75                        break;
     76        }
     77       
     78        fd_list_insert_before(li, &new->chain);
     79       
     80        CHECK_POSIX( pthread_rwlock_unlock(list->o) );
     81}
     82
     83/* Register a new FWD callback */
     84int 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 )
     85{
     86        struct rt_hdl * new;
     87       
     88        TRACE_ENTRY("%p %p %d %p", rt_fwd_cb, cbdata, dir, handler);
     89        CHECK_PARAMS( rt_fwd_cb );
     90        CHECK_PARAMS( (dir >= RT_FWD_REQ) && ( dir <= RT_FWD_ANS) );
     91       
     92        /* Create a new container */
     93        CHECK_MALLOC(new = malloc(sizeof(struct rt_hdl)));
     94        memset(new, 0, sizeof(struct rt_hdl));
     95       
     96        /* Write the content */
     97        fd_list_init(&new->chain, NULL);
     98        new->cbdata     = cbdata;
     99        new->dir        = dir;
     100        new->rt_fwd_cb  = rt_fwd_cb;
     101       
     102        /* Save this in the list */
     103        CHECK_FCT( add_ordered(new, &rt_fwd_list) );
     104       
     105        /* Give it back to the extension if needed */
     106        if (handler)
     107                *handler = (void *)new;
     108       
     109        return 0;
     110}
     111
     112/* Remove it */
     113int fd_rt_fwd_unregister ( struct fd_rt_fwd_hdl * handler, void ** cbdata )
     114{
     115        struct rt_hdl * del;
     116        TRACE_ENTRY( "%p %p", handler, cbdata);
     117        CHECK_PARAMS( handler );
     118       
     119        del = (struct rt_hdl *)handler;
     120        CHECK_PARAMS( del->chain.head == &rt_fwd_list );
     121       
     122        /* Unlink */
     123        CHECK_POSIX( pthread_rwlock_wrlock(&rt_fwd_lock) );
     124        fd_list_unlink(&del->chain);
     125        CHECK_POSIX( pthread_rwlock_unlock(&rt_fwd_lock) );
     126       
     127        if (cbdata)
     128                *cbdata = del->cbdata;
     129       
     130        free(del);
     131        return 0;
     132}
     133
     134/* Register a new OUT callback */
     135int 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 )
     136{
     137        struct rt_hdl * new;
     138       
     139        TRACE_ENTRY("%p %p %d %p", rt_out_cb, cbdata, priority, handler);
     140        CHECK_PARAMS( rt_out_cb );
     141       
     142        /* Create a new container */
     143        CHECK_MALLOC(new = malloc(sizeof(struct rt_hdl)));
     144        memset(new, 0, sizeof(struct rt_hdl));
     145       
     146        /* Write the content */
     147        fd_list_init(&new->chain, NULL);
     148        new->cbdata     = cbdata;
     149        new->prio       = priority;
     150        new->rt_out_cb  = rt_out_cb;
     151       
     152        /* Save this in the list */
     153        CHECK_FCT( add_ordered(new, &rt_out_list) );
     154       
     155        /* Give it back to the extension if needed */
     156        if (handler)
     157                *handler = (void *)new;
     158       
     159        return 0;
     160}
     161
     162/* Remove it */
     163int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata )
     164{
     165        struct rt_hdl * del;
     166        TRACE_ENTRY( "%p %p", handler, cbdata);
     167        CHECK_PARAMS( handler );
     168       
     169        del = (struct rt_hdl *)handler;
     170        CHECK_PARAMS( del->chain.head == &rt_out_list );
     171       
     172        /* Unlink */
     173        CHECK_POSIX( pthread_rwlock_wrlock(&rt_out_lock) );
     174        fd_list_unlink(&del->chain);
     175        CHECK_POSIX( pthread_rwlock_unlock(&rt_out_lock) );
     176       
     177        if (cbdata)
     178                *cbdata = del->cbdata;
     179       
     180        free(del);
     181        return 0;
     182}
     183
     184/********************************************************************************/
     185/*                   Second part : the routing threads                          */
     186/********************************************************************************/
     187
     188/* Note: in the first version, we only create one thread of each kind.
     189 We could improve the scalability by using the threshold feature of the queues fd_g_incoming and fd_g_outgoing
     190 ( fd_g_local is managed by the dispatch thread ) to create additional threads if a queue is filling up.
     191 */
     192
     193/* Function to return an error to an incoming request */
     194static int return_error(struct msg * msg, char * error_code)
     195{
     196        struct fd_peer * peer;
     197
     198        /* Get the source of the message */
     199        {
     200                char * id;
     201                CHECK_FCT( fd_msg_source_get( msg, &id ) );
     202               
     203                /* Search the peer with this id */
     204                CHECK_FCT( fd_peer_getbyid( id, (void *)&peer ) );
     205               
     206                if (!peer) {
     207                        TRACE_DEBUG(INFO, "Unable to send error '%s' to deleted peer '%s' in reply to:", error_code, id);
     208                        fd_msg_dump_walk(INFO, msg);
     209                        fd_msg_free(msg);
     210                        return 0;
     211                }
     212        }
     213       
     214        /* Create the error message */
     215        CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, MSGFL_ANSW_ERROR ) );
     216
     217        /* Set the error code */
     218        CHECK_FCT( fd_msg_rescode_set(msg, error_code, NULL, NULL, 1 ) );
     219
     220        /* Send the answer */
     221        CHECK_FCT( fd_out_send(&msg, NULL, peer) );
     222       
     223        /* Done */
     224        return 0;
     225}
     226
     227
     228/* The (routing-in) thread -- see description in freeDiameter.h */
     229static void * routing_in_thr(void * arg)
     230{
     231        TRACE_ENTRY("%p", arg);
     232       
     233        /* Set the thread name */
     234        if (arg) {
     235                char buf[48];
     236                snprintf(buf, sizeof(buf), "Routing-IN %p", arg);
     237                fd_log_threadname ( buf );
     238        } else {
     239                fd_log_threadname ( "Routing-IN" );
     240        }
     241       
     242        /* Main thread loop */
     243        do {
     244                struct msg * msg;
     245                struct msg_hdr * hdr;
     246                int is_req = 0;
     247                int is_err = 0;
     248               
     249                /* Test if we were told to stop */
     250                pthread_testcancel();
     251               
     252                /* Get the next message from the incoming queue */
     253                CHECK_FCT_DO( fd_fifo_get ( fd_g_incoming, &msg ), goto fatal_error );
     254               
     255                if (TRACE_BOOL(FULL)) {
     256                        TRACE_DEBUG(FULL, "Picked next message:");
     257                        fd_msg_dump_one(FULL, msg);
     258                }
     259               
     260                /* Read the message header */
     261                CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto fatal_error );
     262                is_req = hdr->msg_flags & CMD_FLAG_REQUEST;
     263                is_err = hdr->msg_flags & CMD_FLAG_ERROR;
     264               
     265                /* Handle incorrect bits */
     266                if (is_req && is_err) {
     267                        CHECK_FCT_DO( return_error( msg, "DIAMETER_INVALID_HDR_BITS"), goto fatal_error );
     268                        continue;
     269                }
     270               
     271               
     272               
     273
     274       
     275       
     276        } while (1);
     277       
     278fatal_error:
     279        TRACE_DEBUG(INFO, "An error occurred in routing module! IN thread is terminating...");
     280        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
     281        return NULL;
     282}
     283
    38284/* Note: after testing if the message is to be handled locally, we should test for decorated NAI
    39285  (draft-ietf-dime-nai-routing-04 section 4.4) */
     286 
    40287/* Note2: if the message is still for local delivery, we should test for duplicate
    41288  (draft-asveren-dime-dupcons-00). This may conflict with path validation decisions, no clear answer yet */
    42289
     290
     291
    43292/* Initialize the routing module */
    44293int fd_rt_init(void)
    45294{
     295        TODO("Start the routing threads");
    46296        return ENOTSUP;
    47297}
     
    50300int fd_rt_fini(void)
    51301{
     302        TODO("Stop the routing threads");
    52303        return ENOTSUP;
    53304}
    54305
    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 );
     306
     307
  • include/freeDiameter/freeDiameter.h

    r85 r86  
    286286
    287287/*
     288 * FUNCTION:    fd_peer_getbyid
     289 *
     290 * PARAMETERS:
     291 *  diamid      : A \0 terminated string.
     292 *  peer        : The peer is stored here if it exists.
     293 *
     294 * DESCRIPTION:
     295 *   Search a peer by its Diameter-Id.
     296 *
     297 * RETURN VALUE:
     298 *  0   : *peer has been updated (to NULL if the peer is not found).
     299 * !0   : An error occurred.
     300 */
     301int fd_peer_getbyid( char * diamid, struct peer_hdr ** peer );
     302
     303/*
    288304 * FUNCTION:    peer_validate_register
    289305 *
     
    481497enum fd_rt_fwd_dir {
    482498        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 */
     499        RT_FWD_ALL = 2, /* The callback will be called on all forwarded messages (requests and answers )*/
     500        RT_FWD_ANS = 3  /* The callback will be called on answers and errors only */
    485501};     
    486502
     
    497513 * DESCRIPTION:
    498514 *   Register a new callback for forwarded messages. See explanations above.
     515 * Note that there is no guaranteed order for the callbacks calls.
    499516 *
    500517 * RETURN VALUE:
Note: See TracChangeset for help on using the changeset viewer.