Mercurial > hg > freeDiameter
comparison libfreeDiameter/messages.c @ 7:e5af94b04946
Added dispatch module and tests
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Fri, 04 Sep 2009 18:05:25 +0900 |
parents | 883311bf7df3 |
children | 0e2b57789361 |
comparison
equal
deleted
inserted
replaced
6:b0d377c79d80 | 7:e5af94b04946 |
---|---|
2135 | 2135 |
2136 return 0; | 2136 return 0; |
2137 } | 2137 } |
2138 | 2138 |
2139 /***************************************************************************************************************/ | 2139 /***************************************************************************************************************/ |
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 */ | |
2146 int 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 | |
2226 no_error: | |
2227 CHECK_POSIX(pthread_rwlock_unlock(&fd_disp_lock) ); | |
2228 return 0; | |
2229 | |
2230 error: | |
2231 CHECK_POSIX_DO(pthread_rwlock_unlock(&fd_disp_lock), /* ignore */ ); | |
2232 return ret; | |
2233 } |