Mercurial > hg > freeDiameter
comparison libfdproto/messages.c @ 690:a29e4201d511
It seems FreeBSD does not unstack cancelation cleanups if we skip the pthread_cleanup_pop call
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 20 Jan 2011 15:38:12 +0900 |
parents | 933d098fc75d |
children | 289632905e19 |
comparison
equal
deleted
inserted
replaced
689:933d098fc75d | 690:a29e4201d511 |
---|---|
2219 | 2219 |
2220 /***************************************************************************************************************/ | 2220 /***************************************************************************************************************/ |
2221 /* Macro to check if further callbacks must be called */ | 2221 /* Macro to check if further callbacks must be called */ |
2222 #define TEST_ACTION_STOP() \ | 2222 #define TEST_ACTION_STOP() \ |
2223 if ((*msg == NULL) || (*action != DISP_ACT_CONT)) \ | 2223 if ((*msg == NULL) || (*action != DISP_ACT_CONT)) \ |
2224 goto no_error; | 2224 goto out; |
2225 | 2225 |
2226 /* Call all dispatch callbacks for a given message */ | 2226 /* Call all dispatch callbacks for a given message */ |
2227 int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, const char ** error_code) | 2227 int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, const char ** error_code) |
2228 { | 2228 { |
2229 struct dictionary * dict; | 2229 struct dictionary * dict; |
2230 struct dict_object * app; | 2230 struct dict_object * app; |
2231 struct dict_object * cmd; | 2231 struct dict_object * cmd; |
2232 struct avp * avp; | 2232 struct avp * avp; |
2233 struct fd_list * cb_list; | 2233 struct fd_list * cb_list; |
2234 int ret = 0; | 2234 int ret = 0, r2; |
2235 | 2235 |
2236 TRACE_ENTRY("%p %p %p %p", msg, session, action, error_code); | 2236 TRACE_ENTRY("%p %p %p %p", msg, session, action, error_code); |
2237 CHECK_PARAMS( msg && CHECK_MSG(*msg) && action); | 2237 CHECK_PARAMS( msg && CHECK_MSG(*msg) && action); |
2238 | 2238 |
2239 if (error_code) | 2239 if (error_code) |
2243 /* Take the dispatch lock */ | 2243 /* Take the dispatch lock */ |
2244 CHECK_FCT( pthread_rwlock_rdlock(&fd_disp_lock) ); | 2244 CHECK_FCT( pthread_rwlock_rdlock(&fd_disp_lock) ); |
2245 pthread_cleanup_push( fd_cleanup_rwlock, &fd_disp_lock ); | 2245 pthread_cleanup_push( fd_cleanup_rwlock, &fd_disp_lock ); |
2246 | 2246 |
2247 /* First, call the DISP_HOW_ANY callbacks */ | 2247 /* First, call the DISP_HOW_ANY callbacks */ |
2248 CHECK_FCT_DO( ret = fd_disp_call_cb_int( NULL, msg, NULL, session, action, NULL, NULL, NULL, NULL ), goto error ); | 2248 CHECK_FCT_DO( ret = fd_disp_call_cb_int( NULL, msg, NULL, session, action, NULL, NULL, NULL, NULL ), goto out ); |
2249 | 2249 |
2250 TEST_ACTION_STOP(); | 2250 TEST_ACTION_STOP(); |
2251 | 2251 |
2252 /* 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 */ | 2252 /* 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 */ |
2253 CHECK_PARAMS_DO(cmd = (*msg)->msg_model, { ret = EINVAL; goto error; } ); | 2253 CHECK_PARAMS_DO(cmd = (*msg)->msg_model, { ret = EINVAL; goto out; } ); |
2254 | 2254 |
2255 /* Now resolve message application */ | 2255 /* Now resolve message application */ |
2256 CHECK_FCT_DO( ret = fd_dict_getdict( cmd, &dict ), goto error ); | 2256 CHECK_FCT_DO( ret = fd_dict_getdict( cmd, &dict ), goto out ); |
2257 CHECK_FCT_DO( ret = fd_dict_search( dict, DICT_APPLICATION, APPLICATION_BY_ID, &(*msg)->msg_public.msg_appl, &app, 0 ), goto error ); | 2257 CHECK_FCT_DO( ret = fd_dict_search( dict, DICT_APPLICATION, APPLICATION_BY_ID, &(*msg)->msg_public.msg_appl, &app, 0 ), goto out ); |
2258 | 2258 |
2259 if (app == NULL) { | 2259 if (app == NULL) { |
2260 if ((*msg)->msg_public.msg_flags & CMD_FLAG_REQUEST) { | 2260 if ((*msg)->msg_public.msg_flags & CMD_FLAG_REQUEST) { |
2261 if (error_code) | 2261 if (error_code) |
2262 *error_code = "DIAMETER_APPLICATION_UNSUPPORTED"; | 2262 *error_code = "DIAMETER_APPLICATION_UNSUPPORTED"; |
2264 } else { | 2264 } else { |
2265 fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: Received this answer to a local query with an unsupported application %d", (*msg)->msg_public.msg_appl); | 2265 fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: Received this answer to a local query with an unsupported application %d", (*msg)->msg_public.msg_appl); |
2266 fd_msg_free(*msg); | 2266 fd_msg_free(*msg); |
2267 *msg = NULL; | 2267 *msg = NULL; |
2268 } | 2268 } |
2269 goto no_error; | 2269 goto out; |
2270 } | 2270 } |
2271 | 2271 |
2272 /* So start browsing the message */ | 2272 /* So start browsing the message */ |
2273 CHECK_FCT_DO( ret = fd_msg_browse( *msg, MSG_BRW_FIRST_CHILD, &avp, NULL ), goto error ); | 2273 CHECK_FCT_DO( ret = fd_msg_browse( *msg, MSG_BRW_FIRST_CHILD, &avp, NULL ), goto out ); |
2274 while (avp != NULL) { | 2274 while (avp != NULL) { |
2275 /* For unknown AVP, we don't have a callback registered, so just skip */ | 2275 /* For unknown AVP, we don't have a callback registered, so just skip */ |
2276 if (avp->avp_model) { | 2276 if (avp->avp_model) { |
2277 struct dict_object * enumval = NULL; | 2277 struct dict_object * enumval = NULL; |
2278 | 2278 |
2279 /* Get the list of callback for this AVP */ | 2279 /* Get the list of callback for this AVP */ |
2280 CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_AVP, avp->avp_model, &cb_list), goto error ); | 2280 CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_AVP, avp->avp_model, &cb_list), goto out ); |
2281 | 2281 |
2282 /* We search enumerated values only in case of non-grouped AVP */ | 2282 /* We search enumerated values only in case of non-grouped AVP */ |
2283 if ( avp->avp_public.avp_value ) { | 2283 if ( avp->avp_public.avp_value ) { |
2284 struct dict_object * type; | 2284 struct dict_object * type; |
2285 /* Check if the AVP has a constant value */ | 2285 /* Check if the AVP has a constant value */ |
2286 CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &type, 0), goto error ); | 2286 CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &type, 0), goto out ); |
2287 if (type) { | 2287 if (type) { |
2288 struct dict_enumval_request req; | 2288 struct dict_enumval_request req; |
2289 memset(&req, 0, sizeof(struct dict_enumval_request)); | 2289 memset(&req, 0, sizeof(struct dict_enumval_request)); |
2290 req.type_obj = type; | 2290 req.type_obj = type; |
2291 memcpy( &req.search.enum_value, avp->avp_public.avp_value, sizeof(union avp_value) ); | 2291 memcpy( &req.search.enum_value, avp->avp_public.avp_value, sizeof(union avp_value) ); |
2292 CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enumval, 0), goto error ); | 2292 CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enumval, 0), goto out ); |
2293 } | 2293 } |
2294 } | 2294 } |
2295 | 2295 |
2296 /* Call the callbacks */ | 2296 /* Call the callbacks */ |
2297 CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, avp, session, action, app, cmd, avp->avp_model, enumval ), goto error ); | 2297 CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, avp, session, action, app, cmd, avp->avp_model, enumval ), goto out ); |
2298 TEST_ACTION_STOP(); | 2298 TEST_ACTION_STOP(); |
2299 } | 2299 } |
2300 /* Go to next AVP */ | 2300 /* Go to next AVP */ |
2301 CHECK_FCT_DO( ret = fd_msg_browse( avp, MSG_BRW_WALK, &avp, NULL ), goto error ); | 2301 CHECK_FCT_DO( ret = fd_msg_browse( avp, MSG_BRW_WALK, &avp, NULL ), goto out ); |
2302 } | 2302 } |
2303 | 2303 |
2304 /* Now call command and application callbacks */ | 2304 /* Now call command and application callbacks */ |
2305 CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_COMMAND, cmd, &cb_list), goto error ); | 2305 CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_COMMAND, cmd, &cb_list), goto out ); |
2306 CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL ), goto error ); | 2306 CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL ), goto out ); |
2307 TEST_ACTION_STOP(); | 2307 TEST_ACTION_STOP(); |
2308 | 2308 |
2309 if (app) { | 2309 if (app) { |
2310 CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_APPLICATION, app, &cb_list), goto error ); | 2310 CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_APPLICATION, app, &cb_list), goto out ); |
2311 CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL ), goto error ); | 2311 CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL ), goto out ); |
2312 TEST_ACTION_STOP(); | 2312 TEST_ACTION_STOP(); |
2313 } | 2313 } |
2314 | 2314 out: |
2315 ; /* some systems would complain without this */ | |
2315 pthread_cleanup_pop(0); | 2316 pthread_cleanup_pop(0); |
2316 | 2317 |
2317 no_error: | 2318 CHECK_POSIX_DO(r2 = pthread_rwlock_unlock(&fd_disp_lock), /* ignore */ ); |
2318 CHECK_POSIX(pthread_rwlock_unlock(&fd_disp_lock) ); | 2319 return ret ?: r2; |
2319 return 0; | 2320 } |
2320 | 2321 |
2321 error: | 2322 |
2322 CHECK_POSIX_DO(pthread_rwlock_unlock(&fd_disp_lock), /* ignore */ ); | |
2323 return ret; | |
2324 } | |
2325 | |
2326 |