static int pv_get_sdp(sip_msg_t *msg, pv_param_t *param, pv_value_t *res) { sdp_info_t *sdp = NULL; if(msg==NULL || param==NULL) return -1; if(parse_sdp(msg) < 0) { LM_INFO("Unable to parse sdp\n"); return pv_get_null(msg, param, res); } sdp = (sdp_info_t*)msg->body; if (sdp==NULL) { LM_DBG("No SDP\n"); return pv_get_null(msg, param, res); } switch(param->pvn.u.isname.name.n) { case 0: return pv_get_strval(msg, param, res, &sdp->raw_sdp); default: return pv_get_null(msg, param, res); } }
int sdp_keep_codecs_by_name(sip_msg_t* msg, str* codecs, str *media) { sdp_info_t *sdp = NULL; str idslist; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } sdp = (sdp_info_t*)msg->body; if(sdp==NULL) { LM_DBG("No sdp body\n"); return -1; } LM_DBG("attempting to keep codecs in sdp: [%.*s]\n", codecs->len, codecs->s); if(sdpops_build_ids_list(sdp, codecs, &idslist)<0) return -1; if(sdp_keep_codecs_by_id(msg, &idslist, media)<0) return -1; return 0; }
int sdp_with_codecs_by_name(sip_msg_t* msg, str* codecs) { str idslist; sdp_info_t *sdp = NULL; int ret; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } sdp = (sdp_info_t*)msg->body; if(sdp==NULL) { LM_DBG("No sdp body\n"); return -1; } if(sdpops_build_ids_list(sdp, codecs, &idslist)<0) return -1; ret = sdp_with_codecs_by_id(msg, &idslist); /* ret: -1 error; 0 not found */ if(ret<=0) return (ret - 1); return ret; }
int sdp_keep_codecs_by_id(sip_msg_t* msg, str* codecs) { sdp_info_t *sdp = NULL; int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; str sdp_codecs; str tmp_codecs; str rm_codec; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } LM_ERR("attempting to keep codecs in sdp: [%.*s]\n", codecs->len, codecs->s); sdp = (sdp_info_t*)msg->body; sdp_session_num = 0; for(;;) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; LM_DBG("stream %d of %d - payloads [%.*s]\n", sdp_stream_num, sdp_session_num, sdp_stream->payloads.len, sdp_stream->payloads.s); sdp_codecs = sdp_stream->payloads; tmp_codecs = sdp_stream->payloads; while(str_find_token(&tmp_codecs, &rm_codec, ' ')==0 && rm_codec.len>0) { tmp_codecs.len -=(int)(&rm_codec.s[rm_codec.len]-tmp_codecs.s); tmp_codecs.s = rm_codec.s + rm_codec.len; if(sdp_codec_in_str(codecs, &rm_codec, ',')==0) { LM_DBG("codecs [%.*s] - remove [%.*s]\n", sdp_codecs.len, sdp_codecs.s, rm_codec.len, rm_codec.s); sdp_remove_str_codec_id(msg, &sdp_codecs, &rm_codec); sdp_remove_str_codec_id_attrs(msg, sdp_stream, &rm_codec); } } sdp_stream_num++; } sdp_session_num++; } return 0; }
static int w_sdp_get(sip_msg_t* msg, char *avp) { sdp_info_t *sdp = NULL; int_str avp_val; int_str avp_name; static unsigned short avp_type = 0; str s; pv_spec_t *avp_spec = NULL; int sdp_missing=1; s.s = avp; s.len = strlen(s.s); if (pv_locate_name(&s) != s.len) { LM_ERR("invalid parameter\n"); return -1; } if (((avp_spec = pv_cache_get(&s)) == NULL) || avp_spec->type!=PVT_AVP) { LM_ERR("malformed or non AVP %s AVP definition\n", avp); return -1; } if(pv_get_avp_name(0, &avp_spec->pvp, &avp_name, &avp_type)!=0) { LM_ERR("[%s]- invalid AVP definition\n", avp); return -1; } sdp_missing = parse_sdp(msg); if(sdp_missing < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } sdp = (sdp_info_t*)msg->body; if (sdp==NULL) { LM_DBG("No SDP\n"); return -2; } avp_val.s.s = sdp->raw_sdp.s; avp_val.s.len = sdp->raw_sdp.len; LM_DBG("Found SDP %.*s\n", sdp->raw_sdp.len, sdp->raw_sdp.s); if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) { LM_ERR("Failed to add SDP avp"); return -1; } return 1; }
/** * @brief check 'media' matches the value of any 'm=value ...' lines, and that line is active * @return -1 - error; 0 - not found or inactive; 1 - at least one sendrecv, recvonly or sendonly stream */ static int sdp_with_active_media(sip_msg_t *msg, str *media) { int sdp_session_num; int sdp_stream_num; int port_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } LM_DBG("attempting to search for media type: [%.*s]\n", media->len, media->s); sdp_session_num = 0; for(;;) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; LM_DBG("stream %d of %d - media [%.*s]\n", sdp_stream_num, sdp_session_num, sdp_stream->media.len, sdp_stream->media.s); if(media->len==sdp_stream->media.len && strncasecmp(sdp_stream->media.s, media->s, media->len)==0) { port_num = atoi(sdp_stream->port.s); LM_DBG("Port number is %d\n", port_num); if (port_num != 0) { /* Zero port number => inactive */ LM_DBG("sendrecv_mode %.*s\n", sdp_stream->sendrecv_mode.len, sdp_stream->sendrecv_mode.s); if ((sdp_stream->sendrecv_mode.len == 0) || /* No send/recv mode given => sendrecv */ (strncasecmp(sdp_stream->sendrecv_mode.s, "inactive", 8) != 0)) { /* Explicit mode is not inactive */ /* Found an active stream for the correct media type */ return 1; } } } sdp_stream_num++; } sdp_session_num++; } return 0; }
/** * Every time a new dialog is created (from a new INVITE) the dialog * module will call this callback function. We need to track the * dialogs lifespan from this point forward until it is terminated * with a BYE, CANCEL, etc. In the process, we will see if either or * both ends of the conversation are trying to re-negotiate the media. * * This function will setup the other types of dialog callbacks * required to track the lifespan of the dialog. * * * @param did - The dialog ID * @param type - The trigger event type (CREATED) * @param msg - The SIP message that triggered the callback (INVITE) * @param param - The pointer to nothing. As we did not attach * anything to this callback in the dialog module. */ void qos_dialog_created_CB(struct dlg_cell *did, int type, struct dlg_cb_params * params) { qos_ctx_t *qos_ctx = NULL; struct sip_msg* msg = params->req; unsigned int dir = params->direction, role, other_role; if (dir == DLG_DIR_UPSTREAM) { role = QOS_CALLEE; other_role = QOS_CALLER; } else if (dir == DLG_DIR_DOWNSTREAM) { role = QOS_CALLER; other_role = QOS_CALLEE; } else { LM_ERR("Unknown dir %d\n", dir); return; } if (msg == NULL || msg == FAKED_REPLY) { LM_ERR("Improper msg\n"); return; } /* look only at INVITE */ if (msg->first_line.type != SIP_REQUEST || msg->first_line.u.request.method_value != METHOD_INVITE) { LM_WARN("Dialog create callback called with a non-INVITE req.\n"); return; } qos_ctx = build_new_qos_ctx(); if (qos_ctx==NULL) { /* Error message printed in build_new_qos_ctx() */ return; } LM_DBG("setup_dialog_callbacks( %p , %p )\n", did, qos_ctx); setup_dialog_callbacks(did, qos_ctx); run_create_cbs(qos_ctx, msg); if (0 == parse_sdp(msg)) { lock_get(&qos_ctx->lock); add_sdp(qos_ctx, dir, msg, role, other_role); lock_release(&qos_ctx->lock); } return; }
/** * @brief check 'media' matches the value of any 'm=media port value ...' lines * @return -1 - error; 0 - not found; 1 - found */ static int sdp_with_transport(sip_msg_t *msg, str *transport, int like) { int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } LM_DBG("attempting to search for transport type: [%.*s]\n", transport->len, transport->s); sdp_session_num = 0; for(;;) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; LM_DBG("stream %d of %d - transport [%.*s]\n", sdp_stream_num, sdp_session_num, sdp_stream->transport.len, sdp_stream->transport.s); if (like == 0) { if(transport->len==sdp_stream->transport.len && strncasecmp(sdp_stream->transport.s, transport->s, transport->len)==0) return 1; } else { if (ser_memmem(sdp_stream->transport.s, transport->s, sdp_stream->transport.len, transport->len)!=NULL) return 1; } sdp_stream_num++; } sdp_session_num++; } return 0; }
/** * @brief check 'media' matches the value of any 'm=value ...' lines * @return -1 - error; 0 - not found; 1 - found */ static int sdp_with_media(sip_msg_t *msg, str *media) { sdp_info_t *sdp = NULL; int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } LM_DBG("attempting to search for media type: [%.*s]\n", media->len, media->s); sdp = (sdp_info_t*)msg->body; sdp_session_num = 0; for(;;) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; LM_DBG("stream %d of %d - media [%.*s]\n", sdp_stream_num, sdp_session_num, sdp_stream->media.len, sdp_stream->media.s); if(media->len==sdp_stream->media.len && strncasecmp(sdp_stream->media.s, media->s, media->len)==0) return 1; sdp_stream_num++; } sdp_session_num++; } return 0; }
//open the sdp info static int rtsp_rtp_recv_start(RTSP_HANDLE *rtsp_handle) { char sdp_info[2048] = {0}; if(rtsp_handle == NULL || strlen(rtsp_handle->sdp_info) == 0) { PRINTF("rtsp_rtp_recv_start:the sdp info ERROR\n"); return -1; } SDP_Info* info=parse_sdp(rtsp_handle->sdp_info,strlen(rtsp_handle->sdp_info)); if( !info ) { PRINTF("rtsp_rtp_recv_start:sdp_info NULL\n"); return -1; } PRINTF("rtsp_rtp_recv_start:info->video=%d,audio=%d,config=0x%x,IP=%s,info->type=%d\n", info->video_port,info->audio_port,info->config,info->IP,info->type); /****** video ********/ rtsp_handle->video_handle = rtp_video_open_url(info); if(rtsp_handle->video_handle == NULL) { PRINTF("rtsp_rtp_recv_start:rtsp_handle->video_handle NULL\n"); return -1; }else{ rtsp_handle->video_handle->fCCEvent = (Msg_func)rtsp_handle->fCCEvent; if(rtsp_handle->fGetVideoEs) rtsp_handle->video_handle->fGetVideoEs = (VideoEsCallBack)rtsp_handle->fGetVideoEs; } /******* audio *********/ rtsp_handle->audio_handle= rtp_audio_open_url(info); if(rtsp_handle->audio_handle == NULL) { PRINTF("rtsp_rtp_recv_start:rtsp_handle->audio_handle NULL\n"); return -1; }else { rtsp_handle->audio_handle->fCCEvent = (Msg_func)rtsp_handle->fCCEvent; if(rtsp_handle->fGetAudioEs) rtsp_handle->audio_handle->fGetVideoEs = (VideoEsCallBack)rtsp_handle->fGetAudioEs; } free(info); info=NULL; return 0; }
static int do_for_all_streams(struct sip_msg* msg, str* str1,str * str2, regex_t* re, int op,int desc) { struct sdp_session_cell * cur_session; int rez; if (msg==NULL || msg==FAKED_REPLY) return -1; if(parse_sdp(msg)) { LM_DBG("Message has no SDP\n"); return -1; } if (get_codec_lumps(msg)<0) { LM_ERR("failed to prepare changes for codecs\n"); return -1; } cur_session = msg->sdp->sessions; rez = 0; while(cur_session) { struct sdp_stream_cell * cur_cell = cur_session->streams; while(cur_cell) { rez |= stream_process(msg,cur_cell,str1,str2,re,op,desc); cur_cell = cur_cell->next; } cur_session = cur_session->next; } if( rez <0 ) rez = 0; return rez; }
int sdp_keep_codecs_by_name(sip_msg_t* msg, str* codecs) { str idslist; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } LM_ERR("attempting to keep codecs in sdp: [%.*s]\n", codecs->len, codecs->s); if(sdpops_build_ids_list(codecs, &idslist)<0) return -1; if(sdp_keep_codecs_by_id(msg, &idslist)<0) return -1; return 0; }
static int w_sdp_print(sip_msg_t* msg, char* level, char *bar) { sdp_info_t *sdp = NULL; int llevel = L_DBG; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } if(fixup_get_ivalue(msg, (gparam_p)level, &llevel)!=0) { LM_ERR("unable to get the debug level value\n"); return -1; } sdp = (sdp_info_t*)msg->body; print_sdp(sdp, llevel); return 1; }
bool parse_sap(int length, uint32_t* data){//Parse SAP, false for an unaccepted annoucement, true for everything else (including parsing errors) DBG("Length sap:%d\n",length); struct saphdr* header = (struct saphdr*)data; if(header->version != 1){ fprintf(stderr,"Version 0x%x unsuported!\n",header->version); return true; } if(header->type == 1) return true; data = (uint32_t*)(((unsigned long)data) + 8 + 4*(header->encrypted) + 4*(header->auth_len)); length -= (8 +4*(header->encrypted) + 4*(header->auth_len)); DBG("Length sap without flags:%d\n",length); if(((char*)(data))[1] != '='){//got MIME-Type/payloadType length -= (strlen((char*)data) + 1); data = (uint32_t*)((unsigned long)data + strlen((char*)data) + 1); DBG("Length sap without mime:%d\n",length); } return parse_sdp(length,data); }
/** * * @param did - The dialog structure. The pointer is used as an ID. * @param type - The reason for the callback. DLGCB_REQ_WITHIN * @param msg - The SIP message that causes the callback. * @param param - The qos information */ static void qos_dialog_request_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params) { struct sip_msg* msg = params->req; unsigned int dir = params->direction, role, other_role; qos_ctx_t* qos_ctx = (qos_ctx_t*)*(params->param); if (dir == DLG_DIR_UPSTREAM) { role = QOS_CALLEE; other_role = QOS_CALLER; } else if (dir == DLG_DIR_DOWNSTREAM) { role = QOS_CALLER; other_role = QOS_CALLEE; } else { LM_ERR("Unknown dir %d\n", dir); return; } if (msg->first_line.type == SIP_REQUEST) { if ( (msg->first_line.u.request.method_value == METHOD_INVITE) || (msg->first_line.u.request.method_value == METHOD_UPDATE) || (msg->first_line.u.request.method_value == METHOD_ACK) || (msg->first_line.u.request.method_value == METHOD_PRACK)) { if (0 == parse_sdp(msg)) { lock_get(&qos_ctx->lock); add_sdp(qos_ctx, dir, msg, role, other_role); lock_release(&qos_ctx->lock); } } else { LM_DBG("Ignoring non-carrying SDP req\n"); return; } } else { LM_ERR("not a SIP_REQUEST\n"); return; } return; }
/** * This callback is called on any response message in the lifespan of * the dialog. The callback is called just before the message is * copied to pkg memory so it is still mutable. * * @param did - The dialog structure. The pointer is used as an ID. * @param type - The reason for the callback. DLGCB_CONFIRMED * @param msg - The SIP message that causes the callback. * @param param - The qos information */ static void qos_dialog_response_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params) { struct sip_msg* msg = params->rpl; unsigned int dir = params->direction, role, other_role; qos_ctx_t* qos_ctx = (qos_ctx_t*)*(params->param); if (dir == DLG_DIR_UPSTREAM) { role = QOS_CALLEE; other_role = QOS_CALLER; } else if (dir == DLG_DIR_DOWNSTREAM) { role = QOS_CALLER; other_role = QOS_CALLEE; } else { LM_ERR("Unknown dir %d\n", dir); return; } if (msg->first_line.type == SIP_REPLY) { if (msg->first_line.u.reply.statuscode > 100 && msg->first_line.u.reply.statuscode < 300) { if (0 == parse_sdp(msg)) { lock_get(&qos_ctx->lock); add_sdp(qos_ctx, dir, msg, role, other_role); lock_release(&qos_ctx->lock); } } else if (msg->first_line.u.reply.statuscode > 399 && msg->first_line.u.reply.statuscode < 700) { lock_get(&qos_ctx->lock); remove_sdp(qos_ctx, dir, msg, role, other_role); lock_release(&qos_ctx->lock); } } else { LM_ERR("not a SIP_REPLY\n"); return; } return; }
/* XXX this considers any held stream to mean the call is on hold. correct? */ int sca_call_is_held( sip_msg_t *msg ) { sdp_session_cell_t *session; sdp_stream_cell_t *stream; int n_sess; int n_str; int is_held = 0; int rc; rc = parse_sdp( msg ); if ( rc < 0 ) { LM_ERR( "sca_call_is_held: parse_sdp body failed" ); return( 0 ); } else if ( rc > 0 ) { LM_DBG( "sca_call_is_held: parse_sdp returned %d, no SDP body", rc ); return( 0 ); } /* Cf. modules_k/textops's exported is_audio_on_hold */ for ( n_sess = 0, session = get_sdp_session( msg, n_sess ); session != NULL; n_sess++, session = get_sdp_session( msg, n_sess )) { for ( n_str = 0, stream = get_sdp_stream( msg, n_sess, n_str ); stream != NULL; n_str++, stream = get_sdp_stream( msg, n_sess, n_str )) { if ( stream->is_on_hold ) { is_held = 1; goto done; } } } done: return( is_held ); }
int sdp_with_codecs_by_id(sip_msg_t* msg, str* codecs) { sdp_info_t *sdp = NULL; int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; str sdp_codecs; str tmp_codecs; str fnd_codec; int foundone = 0; int notfound = 0; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } sdp = (sdp_info_t*)msg->body; if(sdp==NULL) { LM_DBG("No sdp body\n"); return -1; } LM_DBG("attempting to search codecs in sdp: [%.*s]\n", codecs->len, codecs->s); sdp_session_num = 0; for(;;) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; LM_DBG("stream %d of %d - payloads [%.*s]\n", sdp_stream_num, sdp_session_num, sdp_stream->payloads.len, sdp_stream->payloads.s); sdp_codecs = sdp_stream->payloads; tmp_codecs = *codecs; while(str_find_token(&tmp_codecs, &fnd_codec, ',')==0 && fnd_codec.len>0) { tmp_codecs.len -=(int)(&fnd_codec.s[fnd_codec.len]-tmp_codecs.s); tmp_codecs.s = fnd_codec.s + fnd_codec.len; if(sdp_codec_in_str(&sdp_codecs, &fnd_codec, ' ')==0) { LM_DBG("codecs [%.*s] - not found [%.*s]\n", sdp_codecs.len, sdp_codecs.s, fnd_codec.len, fnd_codec.s); notfound = 1; } else { LM_DBG("codecs [%.*s] - found [%.*s]\n", sdp_codecs.len, sdp_codecs.s, fnd_codec.len, fnd_codec.s); foundone = 1; } } sdp_stream_num++; } sdp_session_num++; } return (foundone + ((foundone)?notfound:0)); }
/** Helper function for adding media component AVPs for each SDP stream*/ int add_media_components(AAAMessage* aar, struct sip_msg *req, struct sip_msg *rpl, enum dialog_direction direction, AAASession* auth) { int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* req_sdp_session, *rpl_sdp_session; sdp_stream_cell_t* req_sdp_stream, *rpl_sdp_stream; int add_flow = 1; if (!req || !rpl) { return CSCF_RETURN_FALSE; } if (parse_sdp(req) < 0) { LM_ERR("Unable to parse req SDP\n"); return CSCF_RETURN_FALSE; } if (parse_sdp(rpl) < 0) { LM_ERR("Unable to parse res SDP\n"); return CSCF_RETURN_FALSE; } sdp_session_num = 0; //Loop through req sessions and streams and get corresponding rpl sessions and streams and populate avps for (;;) { //we only cater for one session at the moment: TDOD: extend if (sdp_session_num > 0) { break; } req_sdp_session = get_sdp_session(req, sdp_session_num); rpl_sdp_session = get_sdp_session(rpl, sdp_session_num); if (!req_sdp_session || !rpl_sdp_session) { if (!req_sdp_session) LM_ERR("Missing SDP session information from req\n"); if (!rpl_sdp_session) LM_ERR("Missing SDP session information from rpl\n"); break; } sdp_stream_num = 0; for (;;) { req_sdp_stream = get_sdp_stream(req, sdp_session_num, sdp_stream_num); rpl_sdp_stream = get_sdp_stream(rpl, sdp_session_num, sdp_stream_num); if (!req_sdp_stream || !rpl_sdp_stream) { //LM_ERR("Missing SDP stream information\n"); break; } //is this a stream to add to AAR. if (req_sdp_stream->is_rtp) { //check if the src or dst port is 0 and if so then don't add to rx int intportA = atoi(req_sdp_stream->port.s); int intportB = atoi(rpl_sdp_stream->port.s); if(intportA != 0 && intportB != 0){ if(!authorize_video_flow) { if (strncmp(req_sdp_stream->media.s, "video", 5) == 0) { add_flow = 0; } } if(add_flow) { //add this to auth session data add_flow_description((rx_authsessiondata_t*) auth->u.auth.generic_data, sdp_stream_num + 1, &req_sdp_stream->media, &req_sdp_session->ip_addr, &req_sdp_stream->port, &rpl_sdp_session->ip_addr, &rpl_sdp_stream->port, &rpl_sdp_stream->transport, &req_sdp_stream->raw_stream, &rpl_sdp_stream->raw_stream, direction, 0 /*This is a new mcd, we are not setting it as active*/); rx_add_media_component_description_avp(aar, sdp_stream_num + 1, &req_sdp_stream->media, &req_sdp_session->ip_addr, &req_sdp_stream->port, &rpl_sdp_session->ip_addr, &rpl_sdp_stream->port, &rpl_sdp_stream->transport, &req_sdp_stream->raw_stream, &rpl_sdp_stream->raw_stream, direction); } add_flow = 1; } } sdp_stream_num++; } sdp_session_num++; } free_sdp((sdp_info_t**) (void*) &req->body); free_sdp((sdp_info_t**) (void*) &rpl->body); return 0; }
static void rtsp_parse_thread(void *rtsp_handle2) { SDP_Info* sdp_info=NULL; RTSP_HANDLE *rtsp_handle = (RTSP_HANDLE *)rtsp_handle2; // char url[1024] = {0}; char buff[512] = {0}; rtsp_client_t *handle = rtsp_handle->client; int ret = 0; int x = 0; if(handle == NULL) { PRINTF("rtsp_parse_thread:ERROR,the rtsp handle is NULL\n"); goto MSG_EXIT; } ret = reach_rtsp_connect(handle, rtsp_handle->rtsp_url,"User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)" ); if(ret != 0) { PRINTF("rtsp_parse_thread:ERROR!!!!!!!!! reach_rtsp_connect\n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:*** rtsp_request_describe ***\n"); rtsp_schedule_field( handle, "Accept: application/sdp"); ret = rtsp_request_describe(handle,NULL); if(ret != 200) { PRINTF("rtsp_parse_thread:rtsp_request_describe ERROR!\n"); goto MSG_EXIT; } PRINTF("\nrtsp_parse_thread:*** rtsp_recv_sdp_info ***\n"); ret =rtsp_recv_sdp_info(handle,rtsp_handle->sdp_info,sizeof(rtsp_handle->sdp_info)); if(ret != 0) { PRINTF("rtsp_parse_thread:rtsp_request_describe ERROR! \n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:sdp_info=#%s#",rtsp_handle->sdp_info); /** sdp info **/ sdp_info = parse_sdp(rtsp_handle->sdp_info,strlen(rtsp_handle->sdp_info)); if(sdp_info==NULL){ PRINTF("rtsp_parse_thread:parse_sdp ERROR\n"); goto MSG_EXIT; ; } if( sdp_info->video_port == 0 ) sdp_info->video_port = 8436; if(sdp_info->audio_port == 0 ) sdp_info->audio_port = sdp_info->video_port+2; PRINTF("rtsp_parse_thread:*** rtsp_request_setup ***\n"); sprintf(buff,"Transport: RTP/AVP;unicast;client_port=%d-%d", sdp_info->video_port,sdp_info->video_port+1); rtsp_schedule_field( handle, buff); memset(buff,0,sizeof(buff)); sprintf(buff,"rtsp://%s:554/trackID=1",sdp_info->IP); ret = rtsp_request_setup(handle,buff); //"rtsp://192.168.4.161:554/trackID=1"); if(ret != 200) { PRINTF("rtsp_parse_thread:rtsp_request_setup ERROR! \n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:*** rtsp_request_setup ***\n"); memset(buff,0,sizeof(buff)); sprintf(buff,"Transport: RTP/AVP;unicast;client_port=%d-%d", sdp_info->audio_port,sdp_info->audio_port+1); rtsp_schedule_field( handle,buff);// "Transport: RTP/AVP;unicast;client_port=8502-8503"); memset(buff,0,sizeof(buff)); sprintf(buff,"rtsp://%s:554/trackID=2",sdp_info->IP); ret = rtsp_request_setup(handle, buff);//"rtsp://192.168.4.161:554/trackID=2"); if(ret != 200) { PRINTF("rtsp_parse_thread: rtsp_request_setup ERROR!\n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:*** rtsp_request_play ***\n"); rtsp_schedule_field( handle, "Range: npt=0.000-"); ret = rtsp_request_play(handle, NULL); if(ret != 200) { PRINTF("rtsp_parse_thread:rtsp_request_play ERROR! \n"); goto MSG_EXIT; } //add rtp handle ret = rtsp_rtp_recv_start(rtsp_handle); if( ret < 0){ PRINTF("rtsp_parse_thread:rtsp_rtp_recv_start ERROR! \n"); goto MSG_EXIT; } while(1) { //if need stop if(rtsp_handle ->status == 1 || rtsp_handle->video_handle == NULL || rtsp_handle->audio_handle == NULL) { rtsp_rtp_recv_stop(rtsp_handle); Sleep(1000); rtsp_request_tearoff(handle, ""); Sleep(1000); break; } Sleep(3000); if(x++ != DEFAULT_HEARTBIT_TIME/3) continue; x =0; #if 0 ret = rtsp_request_getparameter(handle, NULL); PRINTF("rtsp_request_play ret =%d\n",ret); if(ret != 200) { PRINTF("ERROR! rtsp_request_play\n"); rtsp_rtp_recv_stop( rtsp_handle); break; } #endif } EXIT: if(handle) rtsp_close(handle ); if(rtsp_handle) { rtsp_handle->fCCEvent=NULL; rtsp_handle->fGetAudioEs=NULL; rtsp_handle->fGetVideoEs=NULL; free(rtsp_handle); rtsp_handle = NULL; } return; MSG_EXIT: if(rtsp_handle != NULL && rtsp_handle->fCCEvent) rtsp_handle->fCCEvent(RTSP_STREAM,MSG_RECV_FAIL); if(handle) rtsp_close(handle ); if(rtsp_handle) { rtsp_handle->fCCEvent=NULL; rtsp_handle->fGetAudioEs=NULL; rtsp_handle->fGetVideoEs=NULL; free(rtsp_handle); rtsp_handle = NULL; } return; }
static int w_sdp_content(sip_msg_t* msg, char* foo, char *bar) { if(parse_sdp(msg)==0 && msg->body!=NULL) return 1; return -1; }
/** * Send a CCR to the OCS based on the SIP message (INVITE ONLY) * @param msg - SIP message * @param direction - orig|term * @param reservation_units - units to try to reserve * @param reservation_units - config route to call when receiving a CCA * @param tindex - transaction index * @param tindex - transaction label * * @returns #CSCF_RETURN_BREAK if OK, #CSCF_RETURN_ERROR on error */ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservation_units, str* incoming_trunk_id, str* outgoing_trunk_id, str* pani, cfg_action_t* action, unsigned int tindex, unsigned int tlabel) { str session_id = {0, 0}, called_asserted_identity = {0, 0}, subscription_id = {0, 0}, asserted_identity = {0, 0}; int subscription_id_type = AVP_EPC_Subscription_Id_Type_End_User_SIP_URI; AAASession* cc_acc_session = NULL; Ro_CCR_t * ro_ccr_data = 0; AAAMessage * ccr = 0; struct ro_session *new_session = 0; struct session_setup_data *ssd; int ret = 0; struct hdr_field *h = 0; char *p; int cc_event_number = 0; //According to IOT tests this should start at 0 int cc_event_type = RO_CC_START; int free_called_asserted_identity = 0; sdp_session_cell_t* msg_sdp_session; sdp_stream_cell_t* msg_sdp_stream; int active_service_identifier; int active_rating_group; int sdp_stream_num = 0; LM_DBG("Sending initial CCR request (%c) for reservation_units [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s]\n", dir==RO_ORIG_DIRECTION?'O':'T', reservation_units, incoming_trunk_id->len, incoming_trunk_id->s, outgoing_trunk_id->len, outgoing_trunk_id->s); ssd = shm_malloc(sizeof (struct session_setup_data)); // lookup structure used to load session info from cdp callback on CCA if (!ssd) { LM_ERR("no more shm mem\n"); goto error; } //getting asserted identity if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) { LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity"); asserted_identity = dlg->from_uri; if (asserted_identity.len > 0 && asserted_identity.s) { p=(char*)memchr(asserted_identity.s, ';',asserted_identity.len); if (p) asserted_identity.len = (p-asserted_identity.s); } } //getting called asserted identity if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) { LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity"); called_asserted_identity = cscf_get_public_identity_from_requri(msg); free_called_asserted_identity = 1; } if (dir == RO_ORIG_DIRECTION) { subscription_id.s = asserted_identity.s; subscription_id.len = asserted_identity.len; } else if (dir == RO_TERM_DIRECTION) { subscription_id.s = called_asserted_identity.s; subscription_id.len = called_asserted_identity.len; } else { LM_CRIT("don't know what to do in unknown mode - should we even get here\n"); goto error; } //getting subscription id type if (strncasecmp(subscription_id.s, "tel:", 4) == 0) { subscription_id_type = Subscription_Type_MSISDN; } else { subscription_id_type = Subscription_Type_IMPU; //default is END_USER_SIP_URI } str mac = {0, 0}; if (get_mac_avp_value(msg, &mac) != 0) LM_DBG(RO_MAC_AVP_NAME" was not set. Using default."); //by default we use voice service id and rate group //then we check SDP - if we find video then we use video service id and rate group LM_DBG("Setting default SID to %d and RG to %d for voice", voice_service_identifier, voice_rating_group); active_service_identifier = voice_service_identifier; active_rating_group = voice_rating_group; //check SDP - if there is video then set default to video, if not set it to audio if (parse_sdp(msg) < 0) { LM_ERR("Unable to parse req SDP\n"); goto error; } msg_sdp_session = get_sdp_session(msg, 0); if (!msg_sdp_session) { LM_ERR("Missing SDP session information from rpl\n"); } else { for (;;) { msg_sdp_stream = get_sdp_stream(msg, 0, sdp_stream_num); if (!msg_sdp_stream) { //LM_ERR("Missing SDP stream information\n"); break; } int intportA = atoi(msg_sdp_stream->port.s); if (intportA != 0 && strncasecmp(msg_sdp_stream->media.s, "video", 5) == 0) { LM_DBG("This SDP has a video component and src ports not equal to 0 - so we set default SID to %d and RG to %d for video", video_service_identifier, video_rating_group); active_service_identifier = video_service_identifier; active_rating_group = video_rating_group; break; } sdp_stream_num++; } } free_sdp((sdp_info_t**) (void*) &msg->body); //create a session object without auth and diameter session id - we will add this later. new_session = build_new_ro_session(dir, 0, 0, &session_id, &dlg->callid, &asserted_identity, &called_asserted_identity, &mac, dlg->h_entry, dlg->h_id, reservation_units, 0, active_rating_group, active_service_identifier, incoming_trunk_id, outgoing_trunk_id, pani); if (!new_session) { LM_ERR("Couldn't create new Ro Session - this is BAD!\n"); goto error; } ssd->action = action; ssd->tindex = tindex; ssd->tlabel = tlabel; ssd->ro_session = new_session; if (!sip_create_ro_ccr_data(msg, dir, &ro_ccr_data, &cc_acc_session, asserted_identity, called_asserted_identity, subscription_id, subscription_id_type, incoming_trunk_id, outgoing_trunk_id, pani)) goto error; if (!ro_ccr_data) goto error; if (!cc_acc_session) goto error; if (!(ccr = Ro_new_ccr(cc_acc_session, ro_ccr_data))) goto error; if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0)) { LM_ERR("Problem adding Vendor specific ID\n"); goto error; } if (!Ro_add_cc_request(ccr, cc_event_type, cc_event_number)) { LM_ERR("Problem adding CC-Request data\n"); goto error; } if (!Ro_add_event_timestamp(ccr, time(NULL))) { LM_ERR("Problem adding Event-Timestamp data\n"); goto error; } if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, mac)) { LM_ERR("Problem adding User-Equipment data\n"); goto error; } if (!Ro_add_subscription_id(ccr, subscription_id_type, &subscription_id)) { LM_ERR("Problem adding Subscription ID data\n"); goto error; } if (!Ro_add_multiple_service_credit_Control(ccr, reservation_units, -1, active_rating_group, active_service_identifier)) { LM_ERR("Problem adding Multiple Service Credit Control data\n"); goto error; } /* before we send, update our session object with CC App session ID and data */ new_session->auth_appid = cc_acc_session->application_id; new_session->auth_session_type = cc_acc_session->type; new_session->ro_session_id.s = (char*) shm_malloc(cc_acc_session->id.len); if (!new_session->ro_session_id.s) { LM_ERR("no more shm mem\n"); goto error; } new_session->ro_session_id.len = cc_acc_session->id.len; memcpy(new_session->ro_session_id.s, cc_acc_session->id.s, cc_acc_session->id.len); LM_DBG("new CC Ro Session ID: [%.*s] stored in shared memory address [%p]\n", cc_acc_session->id.len, cc_acc_session->id.s, new_session); LM_DBG("Sending CCR Diameter message.\n"); // new_session->ccr_sent = 1; //assume we will send successfully cdpb.AAASessionsUnlock(cc_acc_session->hash); if (ro_forced_peer.len > 0) { LM_DBG("Sending message with Peer\n"); ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_initial_ccr, (void *) ssd); } else { LM_DBG("Sending message without Peer and realm is [%.*s]\n", ccr->dest_realm->data.len, ccr->dest_realm->data.s); ret = cdpb.AAASendMessage(ccr, resume_on_initial_ccr, (void *) ssd); } if (ret != 1) { LM_ERR("Failed to send Diameter CCR\n"); // new_session->ccr_sent = 0; goto error; } Ro_free_CCR(ro_ccr_data); LM_DBG("Registering for callbacks on Dialog [%p] and charging session [%p]\n", dlg, new_session); //TODO: if the following fail, we should clean up the Ro session....... if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED | DLGCB_CONFIRMED, dlg_callback_received, (void*) new_session, NULL) != 0) { LM_CRIT("cannot register callback for dialog confirmation\n"); goto error; } counter_inc(ims_charging_cnts_h.initial_ccrs); counter_inc(ims_charging_cnts_h.active_ro_sessions); if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri return RO_RETURN_BREAK; error: LM_DBG("Trying to reserve credit on initial INVITE failed.\n"); if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri Ro_free_CCR(ro_ccr_data); if (cc_acc_session) { cdpb.AAASessionsUnlock(cc_acc_session->hash); cdpb.AAADropSession(cc_acc_session); } if (ssd) shm_free(ssd); return RO_RETURN_ERROR; }
/** * sngtc_callee_answer - handles the SDP offer of the callee * * At this point, we have both offers of the endpoints, and can decide whether * transcoding is needed or not. */ static int sngtc_callee_answer(struct sip_msg *msg) { struct dlg_cell *dlg; struct sngtc_info *info; str caller_sdp, dst; sdp_info_t sdp; str *sdp_ptr; int rc; LM_DBG("sngtc_callee_answer\n"); dlg = dlg_binds.get_dlg(); if (!dlg) { LM_ERR("failed to fetch current dialog\n"); return SNGTC_ERR; } /* get the pointer to the SDP body of the caller */ if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &dst, 0) != 0) { LM_ERR("failed to fetch caller sdp\n"); return SNGTC_ERR; } info = *(struct sngtc_info **)(dst.s); sdp_ptr = &info->caller_sdp; LM_DBG("ptrs: %p %p\n", sdp_ptr, info->caller_sdp.s); caller_sdp.len = sdp_ptr->len; caller_sdp.s = sdp_ptr->s; lock_get(&info->lock); LM_DBG("FETCHED CALLER SDP: '%.*s' [%d]\n", caller_sdp.len, caller_sdp.s, caller_sdp.len); memset(&sdp, 0, sizeof(sdp)); if (parse_sdp_session(&caller_sdp, 0, NULL, &sdp) != 0) { LM_ERR("failed to parse caller sdp body\n"); rc = SNGTC_SDP_ERR; goto out_free; } if (parse_sdp(msg) != 0) { LM_ERR("failed to parse callee sdp body\n"); rc = SNGTC_SDP_ERR; goto out_free; } dst.s = sdp_buffer.s; dst.len = 0; /* perform all 200 OK SDP changes and pre-compute the ACK SDP body */ rc = process_session(msg, info, &caller_sdp, &dst, sdp.sessions, msg->sdp->sessions); if (rc != 0) { LM_ERR("failed to rewrite SDP bodies of the endpoints\n"); goto out_free; } if (!is_processed(info)) { dst.s = sdp_buffer.s; LM_DBG("caller ACK SDP: '%.*s'\n", dst.len, dst.s); info->modified_caller_sdp.s = shm_malloc(dst.len); if (!info->modified_caller_sdp.s) { LM_ERR("no more shm memory\n"); rc = SNGTC_ERR; goto out_free; } memcpy(info->modified_caller_sdp.s, dst.s, dst.len); info->modified_caller_sdp.len = dst.len; } info->flags |= PROCESSED_FLAG; lock_release(&info->lock); if (sdp.sessions) __free_sdp(&sdp); return 1; out_free: free_transcoding_sessions(info->sessions); lock_release(&info->lock); if (sdp.sessions) __free_sdp(&sdp); return rc; }
static int w_sdp_get_line_startswith(sip_msg_t *msg, char *avp, char *s_line) { sdp_info_t *sdp = NULL; str body = {NULL, 0}; str line = {NULL, 0}; char* p = NULL; str s; str sline; int_str avp_val; int_str avp_name; pv_spec_t *avp_spec = NULL; static unsigned short avp_type = 0; int sdp_missing=1; if (s_line == NULL || strlen(s_line) <= 0) { LM_ERR("Search string is null or empty\n"); return -1; } sline.s = s_line; sline.len = strlen(s_line); sdp_missing = parse_sdp(msg); if(sdp_missing < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } sdp = (sdp_info_t *)msg->body; if (sdp_missing || sdp == NULL) { LM_DBG("No SDP\n"); return -2; } body.s = sdp->raw_sdp.s; body.len = sdp->raw_sdp.len; if (body.s==NULL) { LM_ERR("failed to get the message body\n"); return -1; } body.len = msg->len - (body.s - msg->buf); if (body.len==0) { LM_DBG("message body has zero length\n"); return -1; } if (avp == NULL || strlen(avp) <= 0) { LM_ERR("avp variable is null or empty\n"); return -1; } s.s = avp; s.len = strlen(s.s); if (pv_locate_name(&s) != s.len) { LM_ERR("invalid parameter\n"); return -1; } if (((avp_spec = pv_cache_get(&s)) == NULL) || avp_spec->type!=PVT_AVP) { LM_ERR("malformed or non AVP %s AVP definition\n", avp); return -1; } if(pv_get_avp_name(0, &avp_spec->pvp, &avp_name, &avp_type)!=0) { LM_ERR("[%s]- invalid AVP definition\n", avp); return -1; } p = find_sdp_line(body.s, body.s+body.len, sline.s[0]); while (p != NULL) { if (sdp_locate_line(msg, p, &line) != 0) { LM_ERR("sdp_locate_line fail\n"); return -1; } if (strncmp(line.s, sline.s, sline.len) == 0) { avp_val.s.s = line.s; avp_val.s.len = line.len; /* skip ending \r\n if exists */ if (avp_val.s.s[line.len-2] == '\r' && avp_val.s.s[line.len-1] == '\n') { /* add_avp() clones to shm and adds 0-terminating char */ avp_val.s.len -= 2; } if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) { LM_ERR("Failed to add SDP line avp"); return -1; } return 1; } p = find_sdp_line(line.s + line.len, body.s + body.len, sline.s[0]); } return -1; }
/** * @brief remove all SDP lines that begin with prefix * @return -1 - error; 0 - no lines found ; 1..N - N lines deleted */ int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix) { str body = {NULL, 0}; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse SDP\n"); return -1; } if(msg->body == NULL) { LM_DBG("No SDP body\n"); return -1; } body.s = ((sdp_info_t*)msg->body)->raw_sdp.s; body.len = ((sdp_info_t*)msg->body)->raw_sdp.len; if (body.s==NULL) { LM_ERR("failed to get the message body\n"); return -1; } body.len = msg->len - (body.s - msg->buf); if (body.len==0) { LM_DBG("message body has zero length\n"); return -1; } char *ptr = NULL; str line = {NULL, 0}; str remove = {NULL, 0}; int found = 0; struct lump *anchor = NULL; ptr = find_sdp_line(body.s, body.s + body.len, prefix->s[0]); while (ptr) { if (sdp_locate_line(msg, ptr, &line) != 0) { LM_ERR("sdp_locate_line() failed\n"); return -1; } if (body.s + body.len < line.s + prefix->len) // check if strncmp would run too far { //LM_DBG("done searching, prefix string >%.*s< (%d) does not fit into remaining buffer space (%ld) \n", prefix->len, prefix->s, prefix->len, body.s + body.len - line.s); break; } if (strncmp(line.s, prefix->s, prefix->len ) == 0) { //LM_DBG("current remove >%.*s< (%d)\n", remove.len, remove.s, remove.len); if (!found) { //LM_DBG("first match >%.*s< (%d)\n", line.len,line.s,line.len); remove.s = line.s; remove.len = line.len; } else { //LM_DBG("cont. match >%.*s< (%d)\n", line.len,line.s,line.len); if (remove.s + remove.len == line.s) { //LM_DBG("this match is right after previous match\n"); remove.len += line.len; } else { //LM_DBG("there is gap between this and previous match, remove now\n"); anchor = del_lump(msg, remove.s - msg->buf, remove.len, HDR_OTHER_T); if (anchor==NULL) { LM_ERR("failed to remove lump\n"); return -1; } remove.s = line.s; remove.len = line.len; } } found++; //LM_DBG("updated remove >%.*s< (%d)\n", remove.len, remove.s, remove.len); } ptr = find_next_sdp_line(ptr, body.s + body.len, prefix->s[0], NULL); } if (found) { //LM_DBG("remove >%.*s< (%d)\n", remove.len, remove.s, remove.len); anchor = del_lump(msg, remove.s - msg->buf, remove.len, HDR_OTHER_T); if (anchor==NULL) { LM_ERR("failed to remove lump\n"); return -1; } return found; } LM_DBG("no match\n"); return 0; }
/** Helper function for adding media component AVPs for each SDP stream*/ int add_media_components(AAAMessage* aar, struct sip_msg *req, struct sip_msg *rpl, enum dialog_direction direction, str *ip, uint16_t *ip_version) { int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* req_sdp_session, *rpl_sdp_session; sdp_stream_cell_t* req_sdp_stream, *rpl_sdp_stream; if (!req || !rpl) { return RX_RETURN_FALSE; } if (parse_sdp(req) < 0) { LM_ERR("Unable to parse req SDP\n"); return RX_RETURN_FALSE; } if (parse_sdp(rpl) < 0) { LM_ERR("Unable to parse res SDP\n"); return RX_RETURN_FALSE; } sdp_session_num = 0; //Loop through req sessions and streams and get corresponding rpl sessions and streams and populate avps for (;;) { //we only cater for one session at the moment: TDOD: extend if (sdp_session_num > 0) { break; } req_sdp_session = get_sdp_session(req, sdp_session_num); rpl_sdp_session = get_sdp_session(rpl, sdp_session_num); if (!req_sdp_session || !rpl_sdp_session) { if (!req_sdp_session) LM_ERR("Missing SDP session information from req\n"); if (!rpl_sdp_session) LM_ERR("Missing SDP session information from rpl\n"); break; } if (direction == DLG_MOBILE_ORIGINATING) { *ip_version = req_sdp_session->pf; *ip = req_sdp_session->ip_addr; } else if (direction == DLG_MOBILE_TERMINATING) { *ip_version = rpl_sdp_session->pf; *ip = rpl_sdp_session->ip_addr; } sdp_stream_num = 0; for (;;) { req_sdp_stream = get_sdp_stream(req, sdp_session_num, sdp_stream_num); rpl_sdp_stream = get_sdp_stream(rpl, sdp_session_num, sdp_stream_num); if (!req_sdp_stream || !rpl_sdp_stream) { //LM_ERR("Missing SDP stream information\n"); break; } //is this a stream to add to AAR. if (req_sdp_stream->is_rtp) { rx_add_media_component_description_avp(aar, sdp_stream_num + 1, &req_sdp_stream->media, &req_sdp_session->ip_addr, &req_sdp_stream->port, &rpl_sdp_session->ip_addr, &rpl_sdp_stream->port, &rpl_sdp_stream->transport, &req_sdp_stream->raw_stream, &rpl_sdp_stream->raw_stream, direction); } sdp_stream_num++; } sdp_session_num++; } free_sdp((sdp_info_t**) (void*) &req->body); free_sdp((sdp_info_t**) (void*) &rpl->body); return 0; }
/** * @brief assigns common media transport (if any) of 'm' lines to pv argument * @return -1 - error; 0 - not found; 1 - found */ static int w_sdp_transport(sip_msg_t* msg, char *avp) { int_str avp_val; int_str avp_name; static unsigned short avp_type = 0; str s; pv_spec_t *avp_spec = NULL; int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; str *transport; s.s = avp; s.len = strlen(s.s); if (pv_locate_name(&s) != s.len) { LM_ERR("invalid avp parameter %s\n", avp); return -1; } if (((avp_spec = pv_cache_get(&s)) == NULL) || avp_spec->type!=PVT_AVP) { LM_ERR("malformed or non AVP %s\n", avp); return -1; } if (pv_get_avp_name(0, &avp_spec->pvp, &avp_name, &avp_type) != 0) { LM_ERR("invalid AVP definition %s\n", avp); return -1; } if(parse_sdp(msg) < 0) { LM_ERR("unable to parse sdp\n"); return -1; } sdp_session_num = 0; transport = (str *)NULL; for (;;) { sdp_session = get_sdp_session(msg, sdp_session_num); if (!sdp_session) break; sdp_stream_num = 0; for (;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if (!sdp_stream) break; LM_DBG("stream %d of %d - transport [%.*s]\n", sdp_stream_num, sdp_session_num, sdp_stream->transport.len, sdp_stream->transport.s); if (transport) { if (transport->len != sdp_stream->transport.len || strncasecmp(sdp_stream->transport.s, transport->s, transport->len) != 0) { LM_DBG("no common transport\n"); return -2; } } else { transport = &sdp_stream->transport; } sdp_stream_num++; } sdp_session_num++; } if (transport) { avp_val.s.s = transport->s; avp_val.s.len = transport->len; LM_DBG("found common transport '%.*s'\n", transport->len, transport->s); if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) { LM_ERR("failed to add transport avp"); return -1; } } return 1; }
int sca_logic_notify(b2bl_cb_params_t *params, unsigned int b2b_event) { int on_hold = 0; int sdp_session_num = 0, sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; struct sip_msg *msg = params->msg; b2bl_cb_ctx_t *cb_params = params->param; str *shared_line; unsigned int hash_index, appearance; b2b_sca_record_t *record; b2b_sca_call_t *call = NULL; str publish_hdr; unsigned int call_info_appearance; unsigned int call_info_appearance_state = 0; struct hdr_field *call_info; struct call_info_body *callinfo_b; struct to_body *call_info_b; struct to_param *param; if (b2b_sca_shutdown_completed) return B2B_FOLLOW_SCENARIO_CB_RET; if (params == NULL) { LM_ERR("callback event [%d] without cb params\n", b2b_event); return B2B_DROP_MSG_CB_RET; } shared_line = &cb_params->shared_line; hash_index = cb_params->hash_index; appearance = cb_params->appearance; LM_DBG("*** GOT NOTIFICATION TYPE [%d] WITH cb_params [%p]->[%.*s] appearance [%d] on hash index [%d]" " for b2bl entity [%d]\n", b2b_event, cb_params, shared_line->len, shared_line->s, appearance, hash_index, params->entity); if (msg && msg->call_info) { if (0 == parse_call_info_header(msg)) { call_info = msg->call_info; if (call_info) { LM_DBG("BODY=[%p]->[%.*s] sibling=[%p]\n", call_info, call_info->body.len, call_info->body.s, call_info->sibling); callinfo_b = call_info->parsed; while (callinfo_b) { call_info_b = &(callinfo_b->call_info_body); LM_DBG(". body=[%.*s] param_lst=[%p] last_param=[%p]\n", call_info_b->body.len, call_info_b->body.s, call_info_b->param_lst, call_info_b->last_param); param = call_info_b->param_lst; while (param) { LM_DBG(".. [%p]->[%d] [%.*s]=[%.*s]->[%p]\n", param, param->type, param->name.len, param->name.s, param->value.len, param->value.s, param->next); if (param->name.len==APPEARANCE_INDEX_LEN && strncmp(APPEARANCE_INDEX_STR, param->name.s, APPEARANCE_INDEX_LEN)==0) { if (strno2int(¶m->value,&call_info_appearance)<0) { LM_ERR("bad appearance-index [%.*s]\n", param->value.len, param->value.s); return -1; } if (appearance != call_info_appearance) { LM_ERR("got appearance[%d] while expecting[%d]\n", call_info_appearance, appearance); goto next_callinfo_b; } else { LM_DBG("*** GOT APP-INDEX [%d]\n", call_info_appearance); } } else if (param->name.len==APPEARANCE_STATE_LEN && strncmp(APPEARANCE_STATE_STR, param->name.s, APPEARANCE_STATE_LEN)==0) { LM_DBG("*** GOT APP-STATE [%.*s]\n", param->value.len, param->value.s); if (param->value.len == strlen(APP_STATE_HELD_PRIVATE) && strncmp(param->value.s, app_state[HELD_PRIVATE_STATE].s, param->value.len)==0) { call_info_appearance_state = HELD_PRIVATE_STATE; } } param=param->next; } goto handle_appearance; next_callinfo_b: callinfo_b = callinfo_b->next; } call_info = call_info->sibling; } } else { LM_ERR("Unable to parse Call-Info header\n"); return B2B_DROP_MSG_CB_RET; } } handle_appearance: lock_get(&b2b_sca_htable[hash_index].lock); record = b2b_sca_search_record_safe(hash_index, shared_line); if (record == NULL) { lock_release(&b2b_sca_htable[hash_index].lock); LM_ERR("record not found for shared line [%.*s] on hash index [%d]\n", shared_line->len, shared_line->s, hash_index); return B2B_DROP_MSG_CB_RET; } b2b_sca_print_record(record); switch(b2b_event){ case B2B_DESTROY_CB: /* Destroy the sca index record */ shm_free(params->param); b2b_sca_delete_call_record(hash_index, record, appearance); break; case B2B_RE_INVITE_CB: case B2B_CONFIRMED_CB: call = b2b_sca_search_call_safe(record, appearance); if (call == NULL) { LM_ERR("call record not found for shared line [%.*s] with index [%d]\n", shared_line->len, shared_line->s, appearance); lock_release(&b2b_sca_htable[hash_index].lock); return B2B_DROP_MSG_CB_RET; } if (0 == parse_sdp(msg)) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; if(sdp_stream->media.len==AUDIO_STR_LEN && strncmp(sdp_stream->media.s,AUDIO_STR,AUDIO_STR_LEN)==0 && sdp_stream->is_on_hold) { on_hold = 1; break; } sdp_stream_num++; } sdp_session_num++; } if (on_hold) { if (call_info_appearance_state) call->call_state = HELD_PRIVATE_STATE; else call->call_state = HELD_STATE; } else { call->call_state = ACTIVE_STATE; } break; default: LM_ERR("Unexpected event\n"); } /* Prepare PUBLISH Call-Info header. */ if (build_publish_call_info_header(record, &publish_hdr) != 0) { lock_release(&b2b_sca_htable[hash_index].lock); LM_ERR("Unable to build PUBLISH Call-Info header\n"); return B2B_FOLLOW_SCENARIO_CB_RET; } /* Save the record to db. */ if (push_sca_info_to_db(record, appearance, 1) != 0) LM_ERR("DB out of synch\n"); /* Notify the watchers. */ sca_publish(record, &publish_hdr); b2b_sca_delete_record_if_empty(record, hash_index); lock_release(&b2b_sca_htable[hash_index].lock); if (publish_hdr.s != publish_call_info_hdr_buf) pkg_free(publish_hdr.s); return B2B_FOLLOW_SCENARIO_CB_RET; }
/** * @brief remove streams matching the m='media' * @return -1 - error; 0 - not found; >=1 - found */ static int sdp_remove_media(sip_msg_t *msg, str *media) { sdp_info_t *sdp = NULL; int sdp_session_num; int sdp_stream_num; sdp_session_cell_t* sdp_session; sdp_stream_cell_t* sdp_stream; sdp_stream_cell_t* nxt_stream; int ret = 0; char *dstart = NULL; int dlen = 0; struct lump *anchor; if(parse_sdp(msg) < 0) { LM_ERR("Unable to parse sdp\n"); return -1; } LM_DBG("attempting to search for media type: [%.*s]\n", media->len, media->s); sdp = (sdp_info_t*)msg->body; sdp_session_num = 0; for(;;) { sdp_session = get_sdp_session(msg, sdp_session_num); if(!sdp_session) break; sdp_stream_num = 0; for(;;) { sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; LM_DBG("stream %d of %d - media [%.*s]\n", sdp_stream_num, sdp_session_num, sdp_stream->media.len, sdp_stream->media.s); if(media->len==sdp_stream->media.len && strncasecmp(sdp_stream->media.s, media->s, media->len)==0) { /* found - remove */ LM_DBG("removing media stream: %.*s", media->len, media->s); nxt_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num+1); /* skip back 'm=' */ dstart = sdp_stream->media.s - 2; if(!nxt_stream) { /* delete to end of sdp */ dlen = (int)(sdp->text.s + sdp->text.len - dstart); } else { /* delete to start of next stream */ dlen = (int)(nxt_stream->media.s - 2 - dstart); } anchor = del_lump(msg, dstart - msg->buf, dlen, 0); if (anchor == NULL) { LM_ERR("failed to remove media type [%.*s]\n", media->len, media->s); return -1; } ret++; } sdp_stream_num++; } sdp_session_num++; } return ret; }