Navigation


Changeset 7:e5af94b04946 in freeDiameter for libfreeDiameter/messages.c


Ignore:
Timestamp:
Sep 4, 2009, 6:05:25 PM (15 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Added dispatch module and tests

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfreeDiameter/messages.c

    r4 r7  
    21382138
    21392139/***************************************************************************************************************/
     2140/* Macro to check if further callbacks must be called */
     2141#define TEST_ACTION_STOP()                                      \
     2142        if ((*msg == NULL) || (*action != DISP_ACT_CONT))       \
     2143                goto no_error;
     2144
     2145/* Call all dispatch callbacks for a given message */
     2146int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action)
     2147{
     2148        struct dictionary  * dict;
     2149        struct dict_object * app;
     2150        struct dict_object * cmd;
     2151        struct avp * avp;
     2152        struct fd_list * cb_list;
     2153        int ret = 0;
     2154       
     2155        TRACE_ENTRY("%p %p %p", msg, session, action);
     2156        CHECK_PARAMS( msg && CHECK_MSG(*msg) && action);
     2157       
     2158        /* Take the dispatch lock */
     2159        CHECK_FCT( pthread_rwlock_rdlock(&fd_disp_lock) );
     2160        pthread_cleanup_push( fd_cleanup_rwlock, &fd_disp_lock );
     2161       
     2162        /* First, call the DISP_HOW_ANY callbacks */
     2163        CHECK_FCT_DO( ret = fd_disp_call_cb_int( NULL, msg, NULL, session, action, NULL, NULL, NULL, NULL ), goto error );
     2164
     2165        TEST_ACTION_STOP();
     2166       
     2167        /* If we don't know the model at this point, we stop cause we cannot get the dictionary. It's invalid: an error should already have been trigged by ANY callbacks */
     2168        CHECK_PARAMS_DO(cmd = (*msg)->msg_model, { ret = EINVAL; goto error; } );
     2169       
     2170        /* Now resolve message application */
     2171        CHECK_FCT_DO( ret = fd_dict_getdict( cmd, &dict ), goto error );
     2172        CHECK_FCT_DO( ret = fd_dict_search( dict, DICT_APPLICATION, APPLICATION_BY_ID, &(*msg)->msg_public.msg_appl, &app, 0 ), goto error );
     2173       
     2174        if (app == NULL) {
     2175                /* In that case, maybe we should answer a DIAMETER_APPLICATION_UNSUPPORTED error ? Do we do this here ? */
     2176                TRACE_DEBUG(NONE, "Reply DIAMETER_APPLICATION_UNSUPPORTED if it's a request ?");
     2177        }
     2178       
     2179        /* So start browsing the message */
     2180        CHECK_FCT_DO( ret = fd_msg_browse( *msg, MSG_BRW_FIRST_CHILD, &avp, NULL ), goto error );
     2181        while (avp != NULL) {
     2182                /* Sanity */
     2183                ASSERT( avp->avp_public.avp_value );
     2184               
     2185                /* For unknown AVP, we don't have a callback registered, so just skip */
     2186                if (avp->avp_model) {
     2187                        struct dict_object * type, * enumval;
     2188                       
     2189                        /* Get the list of callback for this AVP */
     2190                        CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_AVP, avp->avp_model, &cb_list), goto error );
     2191                       
     2192                        /* Check if the AVP has a constant value */
     2193                        CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &type, 0), goto error );
     2194                        if (type) {
     2195                                struct dict_enumval_request req;
     2196                                memset(&req, 0, sizeof(struct dict_enumval_request));
     2197                                req.type_obj = type;
     2198                                memcpy( &req.search.enum_value, avp->avp_public.avp_value, sizeof(union avp_value) );
     2199                                CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enumval, 0), goto error );
     2200                        } else {
     2201                                /* No enumerated value in this case */
     2202                                enumval = NULL;
     2203                        }
     2204                       
     2205                        /* Call the callbacks */
     2206                        CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, avp, session, action, app, cmd, avp->avp_model, enumval ), goto error );
     2207                        TEST_ACTION_STOP();
     2208                }
     2209                /* Go to next AVP */
     2210                CHECK_FCT_DO(  ret = fd_msg_browse( avp, MSG_BRW_WALK, &avp, NULL ), goto error );
     2211        }
     2212               
     2213        /* Now call command and application callbacks */
     2214        CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_COMMAND, cmd, &cb_list), goto error );
     2215        CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL ), goto error );
     2216        TEST_ACTION_STOP();
     2217       
     2218        if (app) {
     2219                CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_APPLICATION, app, &cb_list), goto error );
     2220                CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL ), goto error );
     2221                TEST_ACTION_STOP();
     2222        }
     2223       
     2224        pthread_cleanup_pop(0);
     2225       
     2226no_error:
     2227        CHECK_POSIX(pthread_rwlock_unlock(&fd_disp_lock) );
     2228        return 0;
     2229       
     2230error:
     2231        CHECK_POSIX_DO(pthread_rwlock_unlock(&fd_disp_lock), /* ignore */ );
     2232        return ret;
     2233}
Note: See TracChangeset for help on using the changeset viewer.