| 286 | |
| 287 | |
| 288 | int async_script_launch(struct sip_msg *msg, struct action* a, |
| 289 | struct script_route_ref *report_route, |
| 290 | str *report_route_param, void **params) |
| 291 | { |
| 292 | struct sip_msg *req; |
| 293 | struct usr_avp *report_avps = NULL, **bak_avps = NULL; |
| 294 | async_launch_ctx *ctx; |
| 295 | int fd = -1; |
| 296 | int bk_rt; |
| 297 | |
| 298 | /* run the function (the action) and get back from it the FD, |
| 299 | * resume function and param */ |
| 300 | if ( a->type!=AMODULE_T || a->elem[0].type!=ACMD_ST || |
| 301 | a->elem[0].u.data==NULL ) { |
| 302 | LM_CRIT("BUG - invalid action for async I/O - it must be" |
| 303 | " a MODULE_T ACMD_ST \n"); |
| 304 | return -1; |
| 305 | } |
| 306 | |
| 307 | if ( (ctx=shm_malloc(sizeof(async_launch_ctx) + ( (report_route&&report_route_param)?report_route_param->len:0)))==NULL) { |
| 308 | LM_ERR("failed to allocate new ctx, forcing sync mode\n"); |
| 309 | return -1; |
| 310 | } |
| 311 | |
| 312 | memset(ctx,0,sizeof(async_launch_ctx)); |
| 313 | |
| 314 | async_status = ASYNC_NO_IO; /*assume defauly status "no IO done" */ |
| 315 | |
| 316 | return_code = ((const acmd_export_t*)(a->elem[0].u.data_const))->function(msg, |
| 317 | (async_ctx*)ctx, |
| 318 | params[0], params[1], params[2], |
| 319 | params[3], params[4], params[5], |
| 320 | params[6], params[7]); |
| 321 | /* what to do now ? */ |
| 322 | if (async_status>=0) { |
| 323 | /* async I/O was successfully launched */ |
| 324 | fd = async_status; |
| 325 | } else if (async_status==ASYNC_NO_FD) { |
| 326 | /* async was successfully launched but without a FD resume |
| 327 | * in this case, we need to push the async ctx back to the |
| 328 | * function, so it can trigger the resume later, by itself */ |
| 329 | } else if (async_status==ASYNC_NO_IO) { |
| 330 | /* no IO, so simply continue with the script */ |
| 331 | shm_free(ctx); |
| 332 | return 1; |
| 333 | } else if (async_status==ASYNC_SYNC) { |
| 334 | /* IO already done in SYNC'ed way */ |
| 335 | goto report; |
| 336 | } else if (async_status==ASYNC_CHANGE_FD) { |
| 337 | LM_ERR("Incorrect ASYNC_CHANGE_FD status usage!" |
| 338 | "You should use this status only from the" |
| 339 | "resume function in case something went wrong" |
| 340 | "and you have other alternatives!\n"); |
| 341 | shm_free(ctx); |
| 342 | return -1; |
| 343 | } else { |
| 344 | /* generic error, go for resume route, report it to script */ |
| 345 | shm_free(ctx); |
no test coverage detected