/* refuse the line */ static void refuse_mline(sdp_message_t *answer,char *mtype,char *proto, int mline) { sdp_message_m_media_add (answer, osip_strdup (mtype), int_2char (0), NULL, osip_strdup (proto)); /* add a payload just to comply with sdp RFC.*/ sdp_message_m_payload_add(answer,mline,int_2char(0)); }
/* to add payloads to the offer, must be called inside the write_offer callback */ void sdp_context_add_payload (sdp_context_t * ctx, sdp_payload_t * payload, char *media) { sdp_message_t *offer = ctx->offer; char *attr_field; if (!ctx->incb) { eXosip_trace (OSIP_ERROR, ("You must not call sdp_context_add_*_payload outside the write_offer callback\n")); abort (); } if (payload->proto == NULL) payload->proto = "RTP/AVP"; /*printf("payload->line=%i payload->pt=%i\n",payload->line, payload->pt);*/ if (sdp_message_m_media_get (offer, payload->line) == NULL) { /*printf("Adding new mline %s \n",media);*/ /* need a new line */ sdp_message_m_media_add (offer, osip_strdup (media), int_2char (payload->localport), NULL, osip_strdup (payload->proto)); if (ctx->relay){ add_relay_info(offer,payload->line,ctx->relay,ctx->relay_session_id); } } sdp_message_m_payload_add (offer, payload->line, int_2char (payload->pt)); if (payload->a_rtpmap != NULL) { attr_field = sstrdup_sprintf ("%i %s", payload->pt, payload->a_rtpmap); sdp_message_a_attribute_add (offer, payload->line, osip_strdup ("rtpmap"), attr_field); } if (payload->a_fmtp != NULL) { attr_field = sstrdup_sprintf ("%i %s", payload->pt, payload->a_fmtp); sdp_message_a_attribute_add (offer, payload->line, osip_strdup ("fmtp"), attr_field); } if (payload->b_as_bandwidth != 0) { if (sdp_message_bandwidth_get(offer,payload->line,0)==NULL){ attr_field = sstrdup_sprintf ("%i", payload->b_as_bandwidth); sdp_message_b_bandwidth_add (offer, payload->line, osip_strdup ("AS"), attr_field); } } }
static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt, bool_t strip_well_known_rtpmaps) { char attr[256]; sdp_message_m_payload_add (msg,line, int_2char (payload_type_get_number(pt))); if (!strip_well_known_rtpmaps || !is_known_rtpmap(pt)){ if (pt->channels>1) snprintf (attr,sizeof(attr),"%i %s/%i/%i", payload_type_get_number(pt), pt->mime_type, pt->clock_rate,pt->channels); else snprintf (attr,sizeof(attr),"%i %s/%i", payload_type_get_number(pt), pt->mime_type, pt->clock_rate); sdp_message_a_attribute_add (msg, line, osip_strdup ("rtpmap"), osip_strdup(attr)); } if (pt->recv_fmtp != NULL) { snprintf (attr,sizeof(attr),"%i %s", payload_type_get_number(pt),pt->recv_fmtp); sdp_message_a_attribute_add (msg, line, osip_strdup ("fmtp"), osip_strdup(attr)); } }
static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc) { sdp_message_t *local; int inet6; char sessid[16]; char sessver[16]; snprintf(sessid,16,"%i",desc->session_id); snprintf(sessver,16,"%i",desc->session_ver); sdp_message_init (&local); if (strchr(desc->addr,':')!=NULL){ inet6=1; }else inet6=0; sdp_message_v_version_set (local, osip_strdup ("0")); sdp_message_o_origin_set (local, osip_strdup (desc->username), osip_strdup (sessid), osip_strdup (sessver), osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"), osip_strdup (desc->addr)); sdp_message_s_name_set (local, osip_strdup ("Talk")); if(!sal_media_description_has_dir (desc,SalStreamSendOnly)) { sdp_message_c_connection_add (local, -1, osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"), osip_strdup (desc->addr), NULL, NULL); } else { sdp_message_c_connection_add (local, -1, osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"), inet6 ? osip_strdup ("::0") : osip_strdup ("0.0.0.0"), NULL, NULL); } sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0")); if (desc->bandwidth>0) sdp_message_b_bandwidth_add (local, -1, osip_strdup ("AS"), int_2char(desc->bandwidth)); return local; }
static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc){ const char *mt=NULL; const MSList *elem; const char *addr; const char *dir="sendrecv"; int port; bool_t strip_well_known_rtpmaps; switch (desc->type) { case SalAudio: mt="audio"; break; case SalVideo: mt="video"; break; case SalOther: mt=desc->typeother; break; } if (desc->candidates[0].addr[0]!='\0'){ addr=desc->candidates[0].addr; port=desc->candidates[0].port; }else{ addr=desc->addr; port=desc->port; } /*only add a c= line within the stream description if address are differents*/ if (strcmp(addr,sdp_message_c_addr_get(msg, -1, 0))!=0){ bool_t inet6; if (strchr(addr,':')!=NULL){ inet6=TRUE; }else inet6=FALSE; sdp_message_c_connection_add (msg, lineno, osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"), osip_strdup (addr), NULL, NULL); } sdp_message_m_media_add (msg, osip_strdup (mt), int_2char (port), NULL, osip_strdup ("RTP/AVP")); if (desc->bandwidth>0) sdp_message_b_bandwidth_add (msg, lineno, osip_strdup ("AS"), int_2char(desc->bandwidth)); if (desc->ptime>0) sdp_message_a_attribute_add(msg,lineno,osip_strdup("ptime"), int_2char(desc->ptime)); strip_well_known_rtpmaps=ms_list_size(desc->payloads)>5; if (desc->payloads){ for(elem=desc->payloads;elem!=NULL;elem=elem->next){ add_payload(msg, lineno, (PayloadType*)elem->data,strip_well_known_rtpmaps); } }else{ /* to comply with SDP we cannot have an empty payload type number list */ /* as it happens only when mline is declined with a zero port, it does not matter to put whatever codec*/ sdp_message_m_payload_add (msg,lineno, int_2char (0)); } switch(desc->dir){ case SalStreamSendRecv: /*dir="sendrecv";*/ dir=NULL; break; case SalStreamRecvOnly: dir="recvonly"; break; case SalStreamSendOnly: dir="sendonly"; break; case SalStreamInactive: dir="inactive"; break; } if (dir) sdp_message_a_attribute_add (msg, lineno, osip_strdup (dir),NULL); }
char * sdp_context_get_answer ( sdp_context_t *ctx,sdp_message_t *remote) { sdp_message_t *answer=NULL; char *mtype=NULL, *tmp=NULL; char *proto=NULL, *port=NULL, *pt=NULL; int i, j, ncodec, m_lines_accepted = 0; int err; sdp_payload_t payload; sdp_handler_t *sdph=ctx->handler; sdp_bandwidth_t *sbw=NULL; char *relay; tmp = sdp_message_c_addr_get (remote, 0, 0); if (tmp == NULL) tmp = sdp_message_c_addr_get (remote, -1, 0); if (ctx->localip==NULL) { /* NULL means guess, otherwise we use the address given as localip */ ctx->localip=osip_malloc(128); eXosip_guess_localip(strchr(tmp,':') ? AF_INET6 : AF_INET,ctx->localip,128); } else eXosip_trace(OSIP_INFO1,("Using firewall address in sdp.")); answer = sdp_context_generate_template (ctx); /* for each m= line */ for (i = 0; !sdp_message_endof_media (remote, i); i++) { sdp_payload_init(&payload); mtype = sdp_message_m_media_get (remote, i); proto = sdp_message_m_proto_get (remote, i); port = sdp_message_m_port_get (remote, i); payload.remoteport = osip_atoi (port); payload.proto = proto; payload.line = i; payload.c_addr = sdp_message_c_addr_get (remote, i, 0); if (payload.c_addr == NULL) payload.c_addr = sdp_message_c_addr_get (remote, -1, 0); /*parse relay address if given*/ relay=sdp_message_a_attr_value_get(remote,i,"relay-addr"); if (relay){ payload.relay_host=parse_relay_addr(relay,&payload.relay_port); } payload.relay_session_id=sdp_message_a_attr_value_get(remote,i,"relay-session-id"); /* get application specific bandwidth, if any */ for(j=0;(sbw=sdp_message_bandwidth_get(remote,i,j))!=NULL;j++){ if (strcasecmp(sbw->b_bwtype,"AS")==0) payload.b_as_bandwidth=atoi(sbw->b_bandwidth); } payload.a_ptime=_sdp_message_get_a_ptime(remote,i); if (keywordcmp ("audio", mtype) == 0) { if (sdph->accept_audio_codecs != NULL) { ncodec = 0; /* for each payload type */ for (j = 0; ((pt = sdp_message_m_payload_get (remote, i, j)) != NULL); j++) { payload.pt = osip_atoi (pt); /* get the rtpmap associated to this codec, if any */ payload.a_rtpmap = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "rtpmap"); /* get the fmtp, if any */ payload.a_fmtp = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "fmtp"); /* ask the application if this codec is supported */ err = sdph->accept_audio_codecs (ctx, &payload); if (err == 0 && payload.localport > 0) { ncodec++; /* codec accepted */ if (ncodec == 1) { /* first codec accepted, setup the line */ sdp_message_m_media_add (answer, osip_strdup (mtype), int_2char (payload. localport), NULL, osip_strdup (proto)); /* and accept the remote relay addr if we planned to use our own */ if (ctx->relay!=NULL && relay){ add_relay_info(answer,i,relay,payload.relay_session_id); } } /* add the payload, rtpmap, fmtp */ sdp_message_m_payload_add (answer, i, int_2char (payload. pt)); if (payload.a_rtpmap != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("rtpmap"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_rtpmap)); } if (payload.a_fmtp != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("fmtp"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_fmtp)); } if (payload.b_as_bandwidth != 0) { if (sdp_message_bandwidth_get(answer,i,0)==NULL) sdp_message_b_bandwidth_add (answer, i, osip_strdup ("AS"), sstrdup_sprintf ("%i", payload. b_as_bandwidth)); } } } if (ncodec == 0) { /* refuse the line */ refuse_mline(answer,mtype,proto,i); } else m_lines_accepted++; } else { /* refuse this line (leave port to 0) */ refuse_mline(answer,mtype,proto,i); } } else if (keywordcmp ("video", mtype) == 0) { if (sdph->accept_video_codecs != NULL) { ncodec = 0; /* for each payload type */ for (j = 0; ((pt = sdp_message_m_payload_get (remote, i, j)) != NULL); j++) { payload.pt = osip_atoi (pt); /* get the rtpmap associated to this codec, if any */ payload.a_rtpmap = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "rtpmap"); /* get the fmtp, if any */ payload.a_fmtp = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "fmtp"); /* ask the application if this codec is supported */ err = sdph->accept_video_codecs (ctx, &payload); if (err == 0 && payload.localport > 0) { ncodec++; /* codec accepted */ if (ncodec == 1) { /* first codec accepted, setup the line */ sdp_message_m_media_add (answer, osip_strdup (mtype), int_2char (payload.localport), NULL, osip_strdup (proto)); /* and accept the remote relay addr if we planned to use our own */ if (ctx->relay!=NULL && relay){ add_relay_info(answer,i,relay,payload.relay_session_id); } } /* add the payload, rtpmap, fmtp */ sdp_message_m_payload_add (answer, i, int_2char (payload. pt)); if (payload.a_rtpmap != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("rtpmap"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_rtpmap)); } if (payload.a_fmtp != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("fmtp"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_fmtp)); } if (payload.b_as_bandwidth !=0) { if (sdp_message_bandwidth_get(answer,i,0)==NULL) sdp_message_b_bandwidth_add (answer, i, osip_strdup ("AS"), sstrdup_sprintf ("%i", payload. b_as_bandwidth)); } } } if (ncodec == 0) { /* refuse the line */ refuse_mline(answer,mtype,proto,i); } else m_lines_accepted++; } else { /* refuse the line */ refuse_mline(answer,mtype,proto,i); } } } if (ctx->answer!=NULL) sdp_message_free(ctx->answer); ctx->answer = answer; if (m_lines_accepted > 0){ ctx->negoc_status = 200; sdp_message_to_str(answer,&tmp); if (ctx->answerstr!=NULL) osip_free(ctx->answerstr); ctx->answerstr=tmp; return tmp; }else{ ctx->negoc_status = 415; return NULL; } }