static int sip_get_address(osip_message_t *msg, u_int *host, u_short *port) { osip_content_type_t *ctt; sdp_message_t *sdp; char *tmp; int i; int j; if (NULL == (ctt = osip_message_get_content_type(msg))) return 0; if ((NULL == ctt->type) || (NULL == ctt->subtype)) return 0; if (osip_strcasecmp(ctt->type, "application")) return 0; if (osip_strcasecmp(ctt->subtype, "sdp")) return 0; for (i = 0; !osip_list_eol(msg->bodies, i); ++i) { sdp = NULL; sdp_message_init(&sdp); tmp = ((osip_body_t *)osip_list_get(msg->bodies, i))->body; if (sdp_message_parse(sdp, tmp)) { sdp_message_free(sdp); continue; } for (j = 0; NULL != sdp_message_m_media_get(sdp, j); ++j) { if (NULL == (tmp = sdp_message_m_port_get(sdp, j))) continue; *port = atoi(tmp); if (NULL == (tmp = sdp_message_c_addr_get(sdp, -1, 0))) if (NULL == (tmp = sdp_message_c_addr_get(sdp, j, 0))) continue; *host = (u_int)inet_addr(tmp); sdp_message_free(sdp); return 1; } sdp_message_free(sdp); } return 0; }
/* * PROXY_REWRITE_INVITATION_BODY * * rewrites the outgoing INVITATION request or response packet * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */ int proxy_rewrite_invitation_body(osip_message_t *mymsg, int direction){ osip_body_t *body; sdp_message_t *sdp; struct in_addr map_addr, addr_sess, addr_media, outside_addr, inside_addr; int sts; char *bodybuff; int bodybuflen; char clen[8]; /* content length: probably never more than 7 digits !*/ int map_port, msg_port; int media_stream_no; sdp_connection_t *sdp_conn; sdp_media_t *sdp_med; int rtp_direction=0; int have_c_media=0; if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS; /* * get SDP structure */ sts = osip_message_get_body(mymsg, 0, &body); if (sts != 0) { #if 0 if ((MSG_IS_RESPONSE_FOR(mymsg,"INVITE")) && (MSG_IS_STATUS_1XX(mymsg))) { /* 1xx responses *MAY* contain SDP data */ DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: " "no body found in message"); return STS_SUCCESS; } else { /* INVITE request and 200 response *MUST* contain SDP data */ ERROR("rewrite_invitation_body: no body found in message"); return STS_FAILURE; } #else DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: " "no body found in message"); return STS_SUCCESS; #endif } sts = sip_body_to_str(body, &bodybuff, &bodybuflen); if (sts != 0) { ERROR("rewrite_invitation_body: unable to sip_body_to_str"); } sts = sdp_message_init(&sdp); sts = sdp_message_parse (sdp, bodybuff); if (sts != 0) { ERROR("rewrite_invitation_body: unable to sdp_message_parse body"); DUMP_BUFFER(-1, bodybuff, bodybuflen); osip_free(bodybuff); sdp_message_free(sdp); return STS_FAILURE; } osip_free(bodybuff); if (configuration.debuglevel) { /* just dump the buffer */ char *tmp, *tmp2; int tmplen; sts = osip_message_get_body(mymsg, 0, &body); sts = sip_body_to_str(body, &tmp, &tmplen); osip_content_length_to_str(mymsg->content_length, &tmp2); DEBUG("Body before rewrite (clen=%s, strlen=%i):\n%s\n----", tmp2, tmplen, tmp); osip_free(tmp); osip_free(tmp2); } /* * RTP proxy: get ready and start forwarding * start forwarding for each media stream ('m=' item in SIP message) */ /* get outbound address */ if (get_interface_ip(IF_OUTBOUND, &outside_addr) != STS_SUCCESS) { sdp_message_free(sdp); return STS_FAILURE; } /* get inbound address */ if (get_interface_ip(IF_INBOUND, &inside_addr) != STS_SUCCESS) { sdp_message_free(sdp); return STS_FAILURE; } /* figure out what address to use for RTP masquerading */ if (MSG_IS_REQUEST(mymsg)) { if (direction == DIR_INCOMING) { memcpy(&map_addr, &inside_addr, sizeof (map_addr)); rtp_direction = DIR_OUTGOING; } else { memcpy(&map_addr, &outside_addr, sizeof (map_addr)); rtp_direction = DIR_INCOMING; } } else /* MSG_IS_REPONSE(mymsg) */ { if (direction == DIR_INCOMING) { memcpy(&map_addr, &inside_addr, sizeof (map_addr)); rtp_direction = DIR_OUTGOING; } else { memcpy(&map_addr, &outside_addr, sizeof (map_addr)); rtp_direction = DIR_INCOMING; } } DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: SIP[%s %s] RTP[%s %s]", MSG_IS_REQUEST(mymsg)? "RQ" : "RS", (direction==DIR_INCOMING)? "IN" : "OUT", (rtp_direction==DIR_INCOMING)? "IN" : "OUT", utils_inet_ntoa(map_addr)); /* * first, check presence of a 'c=' item on session level */ if (sdp->c_connection==NULL || sdp->c_connection->c_addr==NULL) { /* * No 'c=' on session level, search on media level now * * According to RFC2327, ALL media description must * include a 'c=' item now: */ media_stream_no=0; while (!sdp_message_endof_media(sdp, media_stream_no)) { /* check if n'th media stream is present */ if (sdp_message_c_addr_get(sdp, media_stream_no, 0) == NULL) { ERROR("SDP: have no 'c=' on session level and neither " "on media level (media=%i)",media_stream_no); sdp_message_free(sdp); return STS_FAILURE; } media_stream_no++; } /* while */ } /* Required 'c=' items ARE present */ /* * rewrite 'c=' item on session level if present and not yet done. * remember the original address in addr_sess */ memset(&addr_sess, 0, sizeof(addr_sess)); if (sdp->c_connection && sdp->c_connection->c_addr) { sts = get_ip_by_host(sdp->c_connection->c_addr, &addr_sess); if (sts == STS_FAILURE) { ERROR("SDP: cannot resolve session 'c=' host [%s]", sdp->c_connection->c_addr); sdp_message_free(sdp); return STS_FAILURE; } /* * Rewrite * an IP address of 0.0.0.0 means *MUTE*, don't rewrite such */ if (strcmp(sdp->c_connection->c_addr, "0.0.0.0") != 0) { osip_free(sdp->c_connection->c_addr); sdp->c_connection->c_addr=osip_malloc(HOSTNAME_SIZE); sprintf(sdp->c_connection->c_addr, "%s", utils_inet_ntoa(map_addr)); } else { /* 0.0.0.0 - don't rewrite */ DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: " "got a MUTE c= record (on session level - legal?)"); } } /* * rewrite 'o=' item (originator) on session level if present. */ if (sdp->o_addrtype && sdp->o_addr) { if (strcmp(sdp->o_addrtype, "IP4") != 0) { ERROR("got IP6 in SDP originator - not yet suported by siproxd"); sdp_message_free(sdp); return STS_FAILURE; } osip_free(sdp->o_addr); sdp->o_addr=osip_malloc(HOSTNAME_SIZE); sprintf(sdp->o_addr, "%s", utils_inet_ntoa(map_addr)); } /* * loop through all media descritions, * start RTP proxy and rewrite them */ for (media_stream_no=0;;media_stream_no++) { /* check if n'th media stream is present */ if (sdp_message_m_port_get(sdp, media_stream_no) == NULL) break; /* * check if a 'c=' item is present in this media description, * if so -> rewrite it */ memset(&addr_media, 0, sizeof(addr_media)); have_c_media=0; sdp_conn=sdp_message_connection_get(sdp, media_stream_no, 0); if (sdp_conn && sdp_conn->c_addr) { if (strcmp(sdp_conn->c_addr, "0.0.0.0") != 0) { sts = get_ip_by_host(sdp_conn->c_addr, &addr_media); have_c_media=1; /* have a valid address */ osip_free(sdp_conn->c_addr); sdp_conn->c_addr=osip_malloc(HOSTNAME_SIZE); sprintf(sdp_conn->c_addr, "%s", utils_inet_ntoa(map_addr)); } else { /* 0.0.0.0 - don't rewrite */ DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: got a " "MUTE c= record (media level)"); } } /* start an RTP proxying stream */ if (sdp_message_m_port_get(sdp, media_stream_no)) { msg_port=atoi(sdp_message_m_port_get(sdp, media_stream_no)); if (msg_port > 0) { osip_uri_t *cont_url = NULL; char *client_id=NULL; /* try to get some additional UA specific unique ID. * Try: * 1) User part of Contact header * 2) Host part of Contact header (will be different * between internal UA and external UA) */ if (!osip_list_eol(mymsg->contacts, 0)) cont_url = ((osip_contact_t*)(mymsg->contacts->node->element))->url; if (cont_url) { client_id=cont_url->username; if (client_id == NULL) client_id=cont_url->host; } /* * do we have a 'c=' item on media level? * if not, use the same as on session level */ if (have_c_media == 0) { memcpy(&addr_media, &addr_sess, sizeof(addr_sess)); } /* * Am I running in front of the routing device? Then I cannot * use the external IP to bind a listen socket to, so force * the use of my inbound IP for listening. */ if ((rtp_direction == DIR_INCOMING) && (configuration.outbound_host) && (strcmp(configuration.outbound_host, "")!=0)) { DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: " "in-front-of-NAT-Router"); memcpy(&map_addr, &inside_addr, sizeof (map_addr)); } sts = rtp_start_fwd(osip_message_get_call_id(mymsg), client_id, rtp_direction, media_stream_no, map_addr, &map_port, addr_media, msg_port); if (sts == STS_SUCCESS) { /* and rewrite the port */ sdp_med=osip_list_get(sdp->m_medias, media_stream_no); if (sdp_med && sdp_med->m_port) { osip_free(sdp_med->m_port); sdp_med->m_port=osip_malloc(8); /* 5 digits, \0 + align */ sprintf(sdp_med->m_port, "%i", map_port); DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: " "m= rewrote port to [%i]",map_port); } else { ERROR("rewriting port in m= failed sdp_med=%p, " "m_number_of_port=%p", sdp_med, sdp_med->m_port); } } /* sts == success */ } /* if msg_port > 0 */ } else { /* no port defined - skip entry */ WARN("no port defined in m=(media) stream_no=%i", media_stream_no); continue; } } /* for media_stream_no */ /* remove old body */ sts = osip_list_remove(mymsg->bodies, 0); osip_body_free(body); /* dump new body */ sdp_message_to_str(sdp, &bodybuff); bodybuflen=strlen(bodybuff); /* free sdp structure */ sdp_message_free(sdp); /* include new body */ sip_message_set_body(mymsg, bodybuff, bodybuflen); if (sts != 0) { ERROR("rewrite_invitation_body: unable to sip_message_set_body body"); } /* free content length resource and include new one*/ osip_content_length_free(mymsg->content_length); mymsg->content_length=NULL; sprintf(clen,"%i",bodybuflen); sts = osip_message_set_content_length(mymsg, clen); /* free old body */ osip_free(bodybuff); if (configuration.debuglevel) { /* just dump the buffer */ char *tmp, *tmp2; int tmplen; sts = osip_message_get_body(mymsg, 0, &body); sts = sip_body_to_str(body, &tmp, &tmplen); osip_content_length_to_str(mymsg->content_length, &tmp2); DEBUG("Body after rewrite (clen=%s, strlen=%i):\n%s\n----", tmp2, tmplen, tmp); osip_free(tmp); osip_free(tmp2); } return STS_SUCCESS; }
int parse_sdp_file(arguments_t *a, char addrs[MAX_CHANNELS_IN_SESSION][INET6_ADDRSTRLEN], char ports[MAX_CHANNELS_IN_SESSION][MAX_PORT_LENGTH], char *sdp_buf) { int i; int m_lines = 0; int j = 0; int number_of_port; int number_of_address; int nb_of_accepted_ch = 0; int nb_of_defined_ch = 0; struct sockaddr_in ipv4; struct sockaddr_in6 ipv6; int position = 0; #ifdef _MSC_VER int addr_size; #else char *ep; #endif int m_line_att_pos; char *att_name; char *att_value; BOOL supported_fec = FALSE; BOOL fec_inst_exists = FALSE; char *addr_type = NULL; char *source_filter = NULL; char *tsi = NULL; char *flute_ch = NULL; int flute_ch_number; char *start_time = NULL; char *stop_time = NULL; fec_dec_t *fec_dec; fec_dec_t *current_fec_dec; sdp_message_init(&a->sdp); if(sdp_message_parse(a->sdp, sdp_buf) != 0) { printf("Error: sdp_parse()\n"); fflush(stdout); return -1; } if((source_filter = sdp_attr_get(a->sdp, "source-filter")) == NULL) { printf("Error: Invalid SDP, source-filter not present.\n"); fflush(stdout); return -1; } else { a->src_filt = sf_char2struct(source_filter); a->alc_a.src_addr = a->src_filt->src_addr; } if((tsi = sdp_attr_get(a->sdp, "flute-tsi")) == NULL) { printf("Error: Invalid SDP, TSI not present.\n"); fflush(stdout); return -1; } else { a->alc_a.tsi = (unsigned int)atoi(tsi); } /* Default channel number is one and it is overwrited if there is 'a:flute-ch' in the SDP file. */ flute_ch_number = 1; flute_ch = sdp_attr_get(a->sdp, "flute-ch"); if(flute_ch != NULL) { flute_ch_number = (unsigned int)atoi(flute_ch); } if((addr_type = sdp_message_c_addrtype_get(a->sdp, 0, 0)) == NULL) { printf("Error: Invalid SDP, no valid 'c' field.\n"); fflush(stdout); return -1; } else { if(strcmp(addr_type, "IP4") == 0) { a->alc_a.addr_family = PF_INET; } else if(strcmp(addr_type, "IP6") == 0) { a->alc_a.addr_family = PF_INET6; } else { printf("Error: Invalid SDP, address type invalid.\n"); fflush(stdout); return -1; } } /* fetch session starttime */ start_time = sdp_message_t_start_time_get (a->sdp, 0); if(start_time != NULL) { #ifdef _MSC_VER a->alc_a.start_time = _atoi64(start_time); if(a->alc_a.start_time > (unsigned long long)0xFFFFFFFFFFFFFFFF) { printf("Error: Invalid SDP, start time too big.\n"); fflush(stdout); return -1; } #else a->alc_a.start_time = strtoull(start_time, &ep, 10); if(errno == ERANGE && a->alc_a.start_time == 0xFFFFFFFFFFFFFFFFULL) { printf("Error: Invalid SDP, start time too big.\n"); fflush(stdout); return -1; } #endif } /* fetch session stoptime */ stop_time = sdp_message_t_stop_time_get (a->sdp, 0); if(stop_time != NULL) { #ifdef _MSC_VER a->alc_a.stop_time = _atoi64(stop_time); if(a->alc_a.stop_time > (unsigned long long)0xFFFFFFFFFFFFFFFF) { printf("Error: Invalid SDP, stop time too big.\n"); fflush(stdout); return -1; } #else a->alc_a.stop_time = strtoull(stop_time, &ep, 10); if(errno == ERANGE && a->alc_a.stop_time == 0xFFFFFFFFFFFFFFFFULL) { printf("Error: Invalid SDP, stop time too big.\n"); fflush(stdout); return -1; } #endif if(a->alc_a.stop_time == 0) { a->cont = TRUE; } } /* Session level FEC declaration */ fec_dec = sdp_fec_dec_get(a->sdp); /* Search how many m-lines is defined in SDP */ while(1) { if(sdp_message_endof_media(a->sdp, position) == 0) { /* check that 'proto' field is FLUTE/UDP */ if(strcmp(sdp_message_m_proto_get(a->sdp, position), "FLUTE/UDP") == 0) { /* check that payload number exists */ if(sdp_message_m_payload_get(a->sdp, position, 0) != NULL) { m_lines++; } } position++; } else { break; } } if(m_lines == 0) { printf("Error: Invalid SDP, no valid 'm' field.\n"); fflush(stdout); fec_dec_free(fec_dec); return -1; } for(i = 0; i < m_lines; i++) { m_line_att_pos = 0; while((att_name = sdp_message_a_att_field_get(a->sdp, i, m_line_att_pos)) != NULL) { if(strcmp(att_name, "FEC") == 0) { fec_inst_exists = TRUE; att_value = sdp_message_a_att_value_get(a->sdp, i, m_line_att_pos); if(fec_dec == NULL) { printf("Error: Invalid SDP, FEC-declaration does not exists.\n"); fflush(stdout); return -1; } current_fec_dec = fec_dec; while(current_fec_dec != NULL) { if(current_fec_dec->index == (unsigned int)atoi(att_value)) { if(current_fec_dec->fec_enc_id == COM_NO_C_FEC_ENC_ID) { a->alc_a.fec_enc_id = COM_NO_C_FEC_ENC_ID; a->alc_a.fec_inst_id = 0; supported_fec = TRUE; } else if(current_fec_dec->fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) { a->alc_a.fec_enc_id = SIMPLE_XOR_FEC_ENC_ID; a->alc_a.fec_inst_id = 0; supported_fec = TRUE; } else if(current_fec_dec->fec_enc_id == RS_FEC_ENC_ID) { a->alc_a.fec_enc_id = RS_FEC_ENC_ID; a->alc_a.fec_inst_id = 0; supported_fec = TRUE; } else if(current_fec_dec->fec_enc_id == SB_SYS_FEC_ENC_ID && current_fec_dec->fec_inst_id == REED_SOL_FEC_INST_ID) { a->alc_a.fec_enc_id = SB_SYS_FEC_ENC_ID; a->alc_a.fec_inst_id = REED_SOL_FEC_INST_ID; supported_fec = TRUE; } } current_fec_dec = current_fec_dec->next; } } else if(strcmp(att_name, "FEC-declaration") == 0) { fec_inst_exists = TRUE; att_value = sdp_message_a_att_value_get(a->sdp, i, m_line_att_pos); current_fec_dec = fec_dec_char2struct(att_value); if(current_fec_dec->fec_enc_id == COM_NO_C_FEC_ENC_ID) { a->alc_a.fec_enc_id = COM_NO_C_FEC_ENC_ID; a->alc_a.fec_inst_id = 0; supported_fec = TRUE; } else if(current_fec_dec->fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) { a->alc_a.fec_enc_id = SIMPLE_XOR_FEC_ENC_ID; a->alc_a.fec_inst_id = 0; supported_fec = TRUE; } else if(current_fec_dec->fec_enc_id == RS_FEC_ENC_ID) { a->alc_a.fec_enc_id = RS_FEC_ENC_ID; a->alc_a.fec_inst_id = 0; supported_fec = TRUE; } else if(current_fec_dec->fec_enc_id == SB_SYS_FEC_ENC_ID && current_fec_dec->fec_inst_id == REED_SOL_FEC_INST_ID) { a->alc_a.fec_enc_id = SB_SYS_FEC_ENC_ID; a->alc_a.fec_inst_id = REED_SOL_FEC_INST_ID; supported_fec = TRUE; } fec_dec_free(current_fec_dec); } m_line_att_pos++; } if(fec_inst_exists == FALSE) { supported_fec = TRUE; a->alc_a.fec_enc_id = COM_NO_C_FEC_ENC_ID; a->alc_a.fec_inst_id = 0; } /* how many ports in m-line */ if(sdp_message_m_number_of_port_get(a->sdp, i) == NULL) { number_of_port = 1; } else { number_of_port = atoi(sdp_message_m_number_of_port_get(a->sdp, i)); } /* how many addresses in c-line */ if(sdp_message_c_addr_multicast_int_get(a->sdp, i, 0) == NULL) { number_of_address = 1; } else { number_of_address = atoi(sdp_message_c_addr_multicast_int_get(a->sdp, i, 0)); } if(((number_of_port != 1) && (number_of_address != 1))) { printf("Error: Invalid SDP, confusing number of ports and addresses.\n"); fflush(stdout); fec_dec_free(fec_dec); return -1; } if(number_of_address == 1) { for(j = 0; j < number_of_port; j++) { if(supported_fec == TRUE) { memset(ports[nb_of_accepted_ch], 0, MAX_PORT_LENGTH); memset(addrs[nb_of_accepted_ch], 0, INET6_ADDRSTRLEN); sprintf(ports[nb_of_accepted_ch], "%i", (atoi(sdp_message_m_port_get(a->sdp, i)) + j)); strcpy(addrs[nb_of_accepted_ch], sdp_message_c_addr_get(a->sdp, i, 0)); nb_of_accepted_ch++; } nb_of_defined_ch++; } } else if(number_of_port == 1) { for(j = 0; j < number_of_address; j++) { if(supported_fec == TRUE) { if(a->alc_a.addr_family == PF_INET) { memset(addrs[nb_of_accepted_ch], 0, INET6_ADDRSTRLEN); ipv4.sin_addr.s_addr = htonl(ntohl(inet_addr(a->alc_a.addr)) + j); sprintf(addrs[j], "%s", inet_ntoa(ipv4.sin_addr)); memset(ports[nb_of_accepted_ch], 0, MAX_PORT_LENGTH); sprintf(ports[nb_of_accepted_ch], "%i", atoi(sdp_message_m_port_get(a->sdp, i))); } else if(a->alc_a.addr_family == PF_INET6) { #ifdef _MSC_VER addr_size = sizeof(struct sockaddr_in6); WSAStringToAddress((char*)a->alc_a.addr, AF_INET6, NULL, (struct sockaddr*)&ipv6, &addr_size); #else inet_pton(AF_INET6, a->alc_a.addr, &ipv6.sin6_addr); #endif memset(addrs[nb_of_accepted_ch], 0, INET6_ADDRSTRLEN); #ifdef _MSC_VER addr_size = sizeof(addrs[nb_of_accepted_ch]); WSAAddressToString((struct sockaddr*)&ipv6, sizeof(struct sockaddr_in6), NULL, addrs[nb_of_accepted_ch], &addr_size); #else inet_ntop(AF_INET6, &ipv6.sin6_addr, addrs[nb_of_accepted_ch], sizeof(addrs[nb_of_accepted_ch])); #endif memset(ports[nb_of_accepted_ch], 0, MAX_PORT_LENGTH); sprintf(ports[nb_of_accepted_ch], "%i", atoi(sdp_message_m_port_get(a->sdp, i))); if(j < (a->alc_a.nb_channel - 1)) { if(increase_ipv6_address(&ipv6.sin6_addr) == -1) { printf("Increasing IPv6 address %s is not possible\n", addrs[j]); fec_dec_free(fec_dec); return -1; } } } nb_of_accepted_ch++; } nb_of_defined_ch++; } } } if(flute_ch_number != nb_of_defined_ch) { printf("Error: Invalid SDP, channel number not correct.\n"); fflush(stdout); fec_dec_free(fec_dec); return -1; } a->alc_a.nb_channel = nb_of_accepted_ch; fec_dec_free(fec_dec); return 0; }
int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){ int i,j; const char *mtype,*proto,*port,*addr,*number; sdp_bandwidth_t *sbw=NULL; addr=sdp_message_c_addr_get (msg, -1, 0); if (addr) strncpy(desc->addr,addr,sizeof(desc->addr)); for(j=0;(sbw=sdp_message_bandwidth_get(msg,-1,j))!=NULL;++j){ if (strcasecmp(sbw->b_bwtype,"AS")==0) desc->bandwidth=atoi(sbw->b_bandwidth); } /* for each m= line */ for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { SalStreamDescription *stream=&desc->streams[i]; memset(stream,0,sizeof(*stream)); mtype = sdp_message_m_media_get(msg, i); proto = sdp_message_m_proto_get (msg, i); port = sdp_message_m_port_get(msg, i); stream->proto=SalProtoUnknown; if (proto){ if (strcasecmp(proto,"RTP/AVP")==0) stream->proto=SalProtoRtpAvp; else if (strcasecmp(proto,"RTP/SAVP")==0){ stream->proto=SalProtoRtpSavp; } } addr = sdp_message_c_addr_get (msg, i, 0); if (addr != NULL) strncpy(stream->addr,addr,sizeof(stream->addr)); if (port) stream->port=atoi(port); stream->ptime=_sdp_message_get_a_ptime(msg,i); if (strcasecmp("audio", mtype) == 0){ stream->type=SalAudio; }else if (strcasecmp("video", mtype) == 0){ stream->type=SalVideo; }else { stream->type=SalOther; strncpy(stream->typeother,mtype,sizeof(stream->typeother)-1); } for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){ if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth); } stream->dir=_sdp_message_get_mline_dir(msg,i); /* for each payload type */ for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){ const char *rtpmap,*fmtp; int ptn=atoi(number); PayloadType *pt=payload_type_new(); payload_type_set_number(pt,ptn); /* get the rtpmap associated to this codec, if any */ rtpmap=sdp_message_a_attr_value_get_with_pt(msg, i,ptn,"rtpmap"); if (payload_type_fill_from_rtpmap(pt,rtpmap)==0){ /* get the fmtp, if any */ fmtp=sdp_message_a_attr_value_get_with_pt(msg, i, ptn,"fmtp"); payload_type_set_send_fmtp(pt,fmtp); stream->payloads=ms_list_append(stream->payloads,pt); ms_message("Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate, pt->send_fmtp ? pt->send_fmtp : ""); } } } desc->nstreams=i; return 0; }
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); }
void sdp_context_read_answer (sdp_context_t *ctx, sdp_message_t *remote) { char *mtype; char *proto, *port, *pt; int i, j,err; char *relay; sdp_payload_t payload,arg_payload; sdp_handler_t *sdph=ctx->handler; sdp_bandwidth_t *sbw=NULL; /* 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.localport = osip_atoi (sdp_message_m_port_get (ctx->offer, i)); 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"); 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->get_audio_codecs != NULL) { /* 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 */ memcpy(&arg_payload,&payload,sizeof(payload)); err = sdph->get_audio_codecs (ctx, &arg_payload); } } } else if (keywordcmp ("video", mtype) == 0) { if (sdph->get_video_codecs != NULL) { /* 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 */ memcpy(&arg_payload,&payload,sizeof(payload)); err = sdph->get_video_codecs (ctx, &arg_payload); } } } } }
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; } }
int test_accessor_get_api (sdp_message_t * sdp) { char *tmp; char *tmp2; char *tmp3; char *tmp4; char *tmp5; int i; int k; if (sdp_message_v_version_get (sdp)) printf ("v_version: |%s|\n", sdp_message_v_version_get (sdp)); if (sdp_message_o_username_get (sdp)) printf ("o_originator: |%s|", sdp_message_o_username_get (sdp)); if (sdp_message_o_sess_id_get (sdp)) printf (" |%s|", sdp_message_o_sess_id_get (sdp)); if (sdp_message_o_sess_version_get (sdp) != NULL) printf (" |%s|", sdp_message_o_sess_version_get (sdp)); if (sdp_message_o_nettype_get (sdp)) printf (" |%s|", sdp_message_o_nettype_get (sdp)); if (sdp_message_o_addrtype_get (sdp)) printf (" |%s|", sdp_message_o_addrtype_get (sdp)); if (sdp_message_o_addr_get (sdp)) printf (" |%s|\n", sdp_message_o_addr_get (sdp)); if (sdp_message_s_name_get (sdp)) printf ("s_name: |%s|\n", sdp_message_s_name_get (sdp)); if (sdp_message_i_info_get (sdp, -1)) printf ("i_info: |%s|\n", sdp_message_i_info_get (sdp, -1)); if (sdp_message_u_uri_get (sdp)) printf ("u_uri: |%s|\n", sdp_message_u_uri_get (sdp)); i = 0; do { tmp = sdp_e_email_get (sdp, i); if (tmp != NULL) printf ("e_email: |%s|\n", tmp); i++; } while (tmp != NULL); i = 0; do { tmp = sdp_message_p_phone_get (sdp, i); if (tmp != NULL) printf ("p_phone: |%s|\n", tmp); i++; } while (tmp != NULL); k = 0; tmp = sdp_message_c_nettype_get (sdp, -1, k); tmp2 = sdp_message_c_addrtype_get (sdp, -1, k); tmp3 = sdp_message_c_addr_get (sdp, -1, k); tmp4 = sdp_message_c_addr_multicast_ttl_get (sdp, -1, k); tmp5 = sdp_message_c_addr_multicast_int_get (sdp, -1, k); if (tmp != NULL && tmp4 != NULL && tmp5 != NULL) printf ("c_connection: |%s| |%s| |%s| |%s| |%s|\n", tmp, tmp2, tmp3, tmp4, tmp5); else if (tmp != NULL && tmp4 != NULL) printf ("c_connection: |%s| |%s| |%s| |%s| |%s|\n", tmp, tmp2, tmp3, tmp4, "(null)"); else if (tmp != NULL && tmp5 != NULL) printf ("c_connection: |%s| |%s| |%s| |%s| |%s|\n", tmp, tmp2, tmp3, "(null)", tmp5); k = 0; do { tmp = sdp_message_b_bwtype_get (sdp, -1, k); tmp2 = sdp_message_b_bandwidth_get (sdp, -1, k); if (tmp != NULL && tmp2 != NULL) printf ("b_bandwidth: |%s|:|%s|\n", tmp, tmp2); else if (tmp != NULL) printf ("b_bandwidth: |%s|:|%s|\n", tmp, "(null)"); k++; } while (tmp != NULL); k = 0; do { tmp = sdp_message_t_start_time_get (sdp, k); tmp2 = sdp_message_t_stop_time_get (sdp, k); if (tmp != NULL && tmp2 != NULL) printf ("t_descr_time: |%s| |%s|\n", tmp, tmp2); else if (tmp != NULL) printf ("t_descr_time: |%s| |%s|\n", tmp, "(null)"); i = 0; do { tmp2 = sdp_message_r_repeat_get (sdp, k, i); i++; if (tmp2 != NULL) printf ("r_repeat: |%s|\n", tmp2); } while (tmp2 != NULL); k++; } while (tmp != NULL); /* TODO r */ if (sdp_message_z_adjustments_get (sdp) != NULL) printf ("z_adjustments: |%s|\n", sdp_message_z_adjustments_get (sdp)); tmp = sdp_message_k_keytype_get (sdp, -1); tmp2 = sdp_message_k_keydata_get (sdp, -1); if (tmp != NULL && tmp2 != NULL) printf ("k_key: |%s|:|%s|\n", tmp, tmp2); else if (tmp != NULL) printf ("k_key: |%s|:|%s|\n", tmp, "(null)"); k = 0; do { tmp = sdp_message_a_att_field_get (sdp, -1, k); tmp2 = sdp_message_a_att_value_get (sdp, -1, k); if (tmp != NULL && tmp2 != NULL) printf ("a_attribute: |%s|:|%s|\n", tmp, tmp2); if (tmp != NULL) printf ("a_attribute: |%s|:|%s|\n", tmp, "(null)"); k++; } while (tmp != NULL); i = 0; while (!sdp_message_endof_media (sdp, i)) { tmp = sdp_message_m_media_get (sdp, i); tmp2 = sdp_message_m_port_get (sdp, i); tmp3 = sdp_message_m_number_of_port_get (sdp, i); tmp4 = sdp_message_m_proto_get (sdp, i); if (tmp != NULL) printf ("m_media: |%s|", tmp); else printf ("m_media: |%s|", "(null)"); if (tmp2 != NULL) printf (" |%s|", tmp2); else printf (" |%s|", "(null)"); if (tmp3 != NULL) printf (" |%s|", tmp3); else printf (" |%s|", "(null)"); if (tmp4 != NULL) printf (" |%s|", tmp4); else printf (" |%s|", "(null)"); k = 0; do { tmp = sdp_message_m_payload_get (sdp, i, k); if (tmp != NULL) printf (" |%s|", tmp); k++; } while (tmp != NULL); printf ("\n"); k = 0; do { tmp = sdp_message_c_nettype_get (sdp, i, k); tmp2 = sdp_message_c_addrtype_get (sdp, i, k); tmp3 = sdp_message_c_addr_get (sdp, i, k); tmp4 = sdp_message_c_addr_multicast_ttl_get (sdp, i, k); tmp5 = sdp_message_c_addr_multicast_int_get (sdp, i, k); if (tmp != NULL) printf ("c_connection: |%s| |%s| |%s| |%s| |%s|\n", tmp, tmp2, tmp3, tmp4, tmp5); else printf ("c_connection: |%s|", "(null)"); if (tmp2 != NULL) printf (" |%s|", tmp2); else printf (" |%s|", "(null)"); if (tmp3 != NULL) printf (" |%s|", tmp3); else printf (" |%s|", "(null)"); if (tmp4 != NULL) printf (" |%s|", tmp4); else printf (" |%s|", "(null)"); if (tmp5 != NULL) printf (" |%s|", tmp5); else printf (" |%s|", "(null)"); printf ("\n"); if (tmp != NULL) k++; } while (tmp != NULL); k = 0; do { tmp = sdp_message_b_bwtype_get (sdp, i, k); tmp2 = sdp_message_b_bandwidth_get (sdp, i, k); if (tmp != NULL) printf ("b_bandwidth: |%s|", tmp); else printf ("b_bandwidth: |%s|", "(null)"); if (tmp2 != NULL) printf (":|%s|\n", tmp2); else printf (":|%s|", "(null)"); printf ("\n"); k++; } while (tmp != NULL); tmp = sdp_message_k_keytype_get (sdp, i); tmp2 = sdp_message_k_keydata_get (sdp, i); if (tmp != NULL) printf ("k_key: |%s|", tmp); else printf ("k_key: |%s|", "(null)"); if (tmp2 != NULL) printf (":|%s|", tmp2); else printf (":|%s|", "(null)"); printf ("\n"); k = 0; do { tmp = sdp_message_a_att_field_get (sdp, i, k); tmp2 = sdp_message_a_att_value_get (sdp, i, k); if (tmp != NULL) printf ("a_attribute: |%s|", tmp); else printf ("a_attribute: |%s|", "(null)"); if (tmp2 != NULL) printf (":|%s|", tmp2); else printf (":|%s|", "(null)"); printf ("\n"); k++; } while (tmp != NULL); i++; } return 0; }