static void sdp_parse_media_ice_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) { belle_sip_list_t *attribute_it; belle_sdp_attribute_t *attribute; const char *att_name; const char *value; int nb_ice_candidates = 0; for (attribute_it = belle_sdp_media_description_get_attributes(media_desc); attribute_it != NULL; attribute_it=attribute_it->next) { attribute=BELLE_SDP_ATTRIBUTE(attribute_it->data); att_name = belle_sdp_attribute_get_name(attribute); value = belle_sdp_attribute_get_value(attribute); if ( (nb_ice_candidates < sizeof (stream->ice_candidates)/sizeof(SalIceCandidate)) && (keywordcmp("candidate", att_name) == 0) && (value != NULL)) { SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates]; char proto[4]; int nb = sscanf(value, "%s %u %3s %u %s %d typ %s raddr %s rport %d", candidate->foundation, &candidate->componentID, proto, &candidate->priority, candidate->addr, &candidate->port, candidate->type, candidate->raddr, &candidate->rport); if (strcasecmp("udp",proto)==0 && ((nb == 7) || (nb == 9))) nb_ice_candidates++; else memset(candidate, 0, sizeof(*candidate)); } else if ((keywordcmp("remote-candidates", att_name) == 0) && (value != NULL)) { SalIceRemoteCandidate candidate; unsigned int componentID; int offset; const char *ptr = value; const char *endptr = value + strlen(ptr); while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) { if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) { SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1]; strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr)-1); remote_candidate->port = candidate.port; } ptr += offset; if (ptr < endptr) { if (ptr[offset] == ' ') ptr += 1; } else break; } } else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) { strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag)-1); } else if ((keywordcmp("ice-pwd", att_name) == 0) && (value != NULL)) { strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd) -1); } else if (keywordcmp("ice-mismatch", att_name) == 0) { stream->ice_mismatch = TRUE; } } }
static int _sdp_message_get_mline_dir(sdp_message_t *sdp, int mline){ int i; sdp_attribute_t *attr; for (i=0;(attr=sdp_message_attribute_get(sdp,mline,i))!=NULL;i++){ if (keywordcmp("sendrecv",attr->a_att_field)==0){ return SalStreamSendRecv; }else if (keywordcmp("sendonly",attr->a_att_field)==0){ return SalStreamSendOnly; }else if (keywordcmp("recvonly",attr->a_att_field)==0){ return SalStreamSendOnly; }else if (keywordcmp("inactive",attr->a_att_field)==0){ return SalStreamInactive; } } return SalStreamSendRecv; }
static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) { belle_sip_list_t *attribute_it; belle_sdp_attribute_t *attribute; char tmp[256], tmp2[256]; int valid_count = 0; int nb; memset ( &stream->crypto, 0, sizeof ( stream->crypto ) ); for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc ) ; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL; attribute_it=attribute_it->next ) { attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data ); if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) { nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s", &stream->crypto[valid_count].tag, tmp, tmp2 ); ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'", stream->crypto[valid_count].tag, tmp, tmp2 ); if ( nb == 3 ) { if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 ) stream->crypto[valid_count].algo = AES_128_SHA1_80; else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 ) stream->crypto[valid_count].algo = AES_128_SHA1_32; else { ms_warning ( "Failed to parse crypto-algo: '%s'", tmp ); stream->crypto[valid_count].algo = 0; } if ( stream->crypto[valid_count].algo ) { strncpy ( stream->crypto[valid_count].master_key, tmp2, 41 ); stream->crypto[valid_count].master_key[40] = '\0'; ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'", stream->crypto[valid_count].tag, tmp, stream->crypto[valid_count].master_key ); valid_count++; } } else { ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb ); } } } ms_message ( "Found: %d valid crypto lines", valid_count ); }
/* return the value of attr "field" */ static const char *sdp_message_a_attr_value_get(sdp_message_t *sdp,int pos,const char *field) { int i; sdp_attribute_t *attr; for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){ if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){ return attr->a_att_value; } } return NULL; }
static bool_t sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) { belle_sip_list_t *it; belle_sdp_attribute_t *attribute; belle_sdp_rtcp_fb_attribute_t *fb_attribute; MSList *pt_it; PayloadType *pt; int8_t pt_num; bool_t retval = FALSE; /* Handle rtcp-fb attributes that concern all payload types. */ for (it = belle_sdp_media_description_get_attributes(media_desc); it != NULL; it = it->next) { attribute = BELLE_SDP_ATTRIBUTE(it->data); if (keywordcmp("rtcp-fb", belle_sdp_attribute_get_name(attribute)) == 0) { fb_attribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute); if (belle_sdp_rtcp_fb_attribute_get_id(fb_attribute) == -1) { for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) { pt = (PayloadType *)pt_it->data; apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt); retval = TRUE; } } } } /* Handle rtcp-fb attributes that are specefic to a payload type. */ for (it = belle_sdp_media_description_get_attributes(media_desc); it != NULL; it = it->next) { attribute = BELLE_SDP_ATTRIBUTE(it->data); if (keywordcmp("rtcp-fb", belle_sdp_attribute_get_name(attribute)) == 0) { fb_attribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute); pt_num = belle_sdp_rtcp_fb_attribute_get_id(fb_attribute); for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) { pt = (PayloadType *)pt_it->data; retval = TRUE; if (payload_type_get_number(pt) == (int)pt_num) { apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt); } } } } return retval; }
MSCryptoSuite ms_crypto_suite_build_from_name_params(const MSCryptoSuiteNameParams *descrption){ const char *name=descrption->name, *parameters=descrption->params; if (keywordcmp ( "AES_CM_128_HMAC_SHA1_80",name ) == 0 ){ if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) return MS_NO_CIPHER_SHA1_80; else if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) return MS_AES_128_NO_AUTH; else return MS_AES_128_SHA1_80; }else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",name ) == 0 ){ if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) goto error; if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) return MS_AES_128_NO_AUTH; else return MS_AES_128_SHA1_32; }else if ( keywordcmp ("AES_256_CM_HMAC_SHA1_32", name) == 0 ){ if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) goto error; if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) goto error; return MS_AES_256_SHA1_32; }else if ( keywordcmp ("AES_256_CM_HMAC_SHA1_80", name) == 0 ){ if (parameters && strstr(parameters,"UNENCRYPTED_SRTP")) goto error; if (parameters && strstr(parameters,"UNAUTHENTICATED_SRTP")) goto error; return MS_AES_256_SHA1_80; } error: ms_error("Unsupported crypto suite '%s' with parameters '%s'",name, parameters ? parameters : ""); return MS_CRYPTO_SUITE_INVALID; }
static int _sdp_message_get_a_ptime(sdp_message_t *sdp, int mline){ int i,ret; sdp_attribute_t *attr; for (i=0;(attr=sdp_message_attribute_get(sdp,mline,i))!=NULL;i++){ if (keywordcmp("ptime",attr->a_att_field)==0){ int nb = sscanf(attr->a_att_value,"%i",&ret); /* the return value may depend on how %n is interpreted by the libc: see manpage*/ if (nb == 1){ return ret; }else ms_warning("sdp has a strange a=ptime line (%s) ",attr->a_att_value); } } return 0; }
static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) { belle_sip_list_t *attribute_it; belle_sdp_attribute_t *attribute; char tmp[256], tmp2[256], parameters[256]={0}; int valid_count = 0; int nb; memset ( &stream->crypto, 0, sizeof ( stream->crypto ) ); for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc ) ; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL; attribute_it=attribute_it->next ) { attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data ); if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) { nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s %256s", &stream->crypto[valid_count].tag, tmp, tmp2, parameters ); if ( nb >= 3 ) { MSCryptoSuite cs; MSCryptoSuiteNameParams np; np.name=tmp; np.params=parameters[0]!='\0' ? parameters : NULL; cs=ms_crypto_suite_build_from_name_params(&np); if (cs==MS_CRYPTO_SUITE_INVALID){ ms_warning ( "Failed to parse crypto-algo: '%s'", tmp ); stream->crypto[valid_count].algo = 0; }else{ char *sep; strncpy ( stream->crypto[valid_count].master_key, tmp2, sizeof(stream->crypto[valid_count].master_key)-1 ); sep=strchr(stream->crypto[valid_count].master_key,'|'); if (sep) *sep='\0'; stream->crypto[valid_count].algo = cs; ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'", stream->crypto[valid_count].tag, tmp, stream->crypto[valid_count].master_key ); valid_count++; } }else{ ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb ); } } } ms_message("Found: %d valid crypto lines", valid_count ); }
/* return the value of attr "field" for payload pt at line pos (field=rtpmap,fmtp...)*/ static const char *sdp_message_a_attr_value_get_with_pt(sdp_message_t *sdp,int pos,int pt,const char *field) { int i,tmppt=0,scanned=0; char *tmp; sdp_attribute_t *attr; for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){ if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){ int nb = sscanf(attr->a_att_value,"%i %n",&tmppt,&scanned); /* the return value may depend on how %n is interpreted by the libc: see manpage*/ if (nb == 1 || nb==2 ){ if (pt==tmppt){ tmp=attr->a_att_value+scanned; if (strlen(tmp)>0) return tmp; } }else ms_warning("sdp has a strange a= line (%s) nb=%i",attr->a_att_value,nb); } } return NULL; }
void CScriptDlg::OnChar(char ch) { CScintillaWnd* pSelected = GetSelectedScintilla(); long pos = pSelected->GetCurrentPosition(); CString text = pSelected->GetText(); if(pos > 3) { if(text.GetAt(pos-2) == '=') { if(text.GetAt(pos-3) != '!' && text.GetAt(pos-3) != '<' && text.GetAt(pos-3) != '>') { // we have typed something like x = 0 // check to see if theres an 'if' at the start of the line char linebuf[1000]; int curLine = pSelected->SendMessage(SCI_LINEFROMPOSITION, pos); int LineLength = pSelected->SendMessage(SCI_LINELENGTH, curLine); WORD buflen = sizeof(linebuf); memcpy(linebuf, &buflen, sizeof(buflen)); pSelected->SendMessage(SCI_GETLINE, curLine, reinterpret_cast<LPARAM>(static_cast<char *>(linebuf))); linebuf[LineLength] = '\0'; char* strpos = &linebuf[0]; for(int a = 0; a < LineLength; a++) { if(linebuf[a] == '\t' || linebuf[a] == ' ') strpos ++; else break; } if(keywordcmp(strpos, "if") || keywordcmp(strpos, "while") ) { //okay the user has type something like: if x=0 // so go back a char, insert another = so the user gets // if x==0 pSelected->GotoPosition(pos-1); char equals[] = "="; pSelected->SendMessage(SCI_REPLACESEL, 0, (LPARAM)equals); pos ++; pSelected->GotoPosition(pos); } } } } // The following code enables autoindent and autocolon to help out the programmer. if (ch == '\r' || ch == '\n') { char linebuf[1000]; int curLine = pSelected->SendMessage(SCI_LINEFROMPOSITION, pos+1); int lineLength = pSelected->SendMessage(SCI_LINELENGTH, curLine); if (curLine > 0 && lineLength <= 2) { int prevLineLength = pSelected->SendMessage(SCI_LINELENGTH, curLine - 1); if (prevLineLength < sizeof(linebuf)) { WORD buflen = sizeof(linebuf); memcpy(linebuf, &buflen, sizeof(buflen)); pSelected->SendMessage(SCI_GETLINE, curLine - 1, reinterpret_cast<LPARAM>(static_cast<char *>(linebuf))); linebuf[prevLineLength] = '\0'; bool indent = false; bool addcolon = false; for (int p = 0; linebuf[p]; p++) { // note: space at the end to prevent errors if (keywordcmp(&linebuf[p], "def") || keywordcmp( &linebuf[p], "class") || keywordcmp( &linebuf[p], "for") || keywordcmp( &linebuf[p], "while") || keywordcmp( &linebuf[p], "if")) { addcolon = true; indent = true; } if(keywordcmp(&linebuf[p], ":")) { indent = true; addcolon = false; } } int bracketdepth = 0; for (int p = 0; linebuf[p]; p++) { if (linebuf[p] == '(') bracketdepth ++; if (linebuf[p] == ')') bracketdepth --; if (linebuf[p] != ' ' && linebuf[p] != '\t') linebuf[p] = '\0'; } while(bracketdepth > 0) { pSelected->GotoPosition(pos-1); char colon[] = ")"; pSelected->SendMessage(SCI_REPLACESEL, 0, (LPARAM)colon); pos ++; pSelected->GotoPosition(pos); bracketdepth --; } if(addcolon) { pSelected->GotoPosition(pos-1); char colon[] = ":"; pSelected->SendMessage(SCI_REPLACESEL, 0, (LPARAM)colon); pSelected->GotoPosition(pos+1); } pSelected->SendMessage(SCI_REPLACESEL, 0, (LPARAM)linebuf); if(indent) { char tab[] = "\t"; pSelected->SendMessage(SCI_REPLACESEL, 0, (LPARAM)tab); } } } } if(ch == ')') { char linebuf[1000]; int curLine = pSelected->SendMessage(SCI_LINEFROMPOSITION, pos); int LineLength = pSelected->SendMessage(SCI_LINELENGTH, curLine); WORD buflen = sizeof(linebuf); memcpy(linebuf, &buflen, sizeof(buflen)); pSelected->SendMessage(SCI_GETLINE, curLine, reinterpret_cast<LPARAM>(static_cast<char *>(linebuf))); linebuf[LineLength] = '\0'; int bracketlevel = 0; for( int c = 0; c < LineLength; c++) { if(linebuf[c] == '(') bracketlevel ++; if(linebuf[c] == ')') bracketlevel --; } if(bracketlevel < 0) { pSelected->SendMessage(SCI_SETSEL, pos-1, pos); char blank[] = ""; pSelected->SendMessage(SCI_REPLACESEL, 0, (LPARAM)blank); } } return; }
int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, SalMediaDescription *desc ) { /* typedef struct SalMediaDescription{ int refcount; char addr[64]; char username[64]; int nstreams; int bandwidth; unsigned int session_ver; unsigned int session_id; SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; } SalMediaDescription; */ belle_sdp_connection_t* cnx; belle_sip_list_t* media_desc_it; belle_sdp_media_description_t* media_desc; const char *mtype,*proto; SalStreamDescription *stream; belle_sdp_media_t* media; belle_sip_list_t* mime_params=NULL; belle_sip_list_t* mime_param_it=NULL; belle_sdp_mime_parameter_t* mime_param; PayloadType *pt; belle_sip_list_t* attribute_it; const belle_sdp_attribute_t* attribute; int valid_count = 0; char tmp[256], tmp2[256]; int nb=0; SalStreamDir stream_dir=SalStreamSendRecv; const char* value; desc->n_active_streams = 0; desc->n_total_streams = 0; if ( ( cnx=belle_sdp_session_description_get_connection ( session_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) { strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) ); } if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) { desc->bandwidth=belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ); } /*in some very rare case, session attribute may set stream dir*/ if ( belle_sdp_session_description_get_attribute ( session_desc,"sendrecv" ) ) { stream_dir=SalStreamSendRecv; } else if ( belle_sdp_session_description_get_attribute ( session_desc,"sendonly" ) ) { stream_dir=SalStreamSendOnly; } else if ( belle_sdp_session_description_get_attribute ( session_desc,"recvonly" ) ) { stream_dir=SalStreamRecvOnly; } else if ( belle_sdp_session_description_get_attribute ( session_desc,"inactive" ) ) { stream_dir=SalStreamInactive; } /* Get ICE remote ufrag and remote pwd, and ice_lite flag */ value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag"); if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag)); value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd"); if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd)); value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite"); if (value) desc->ice_lite = TRUE; for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc ) ; media_desc_it!=NULL ; media_desc_it=media_desc_it->next ) { int nb_ice_candidates=0; media_desc=BELLE_SDP_MEDIA_DESCRIPTION ( media_desc_it->data ); stream=&desc->streams[desc->n_total_streams]; media=belle_sdp_media_description_get_media ( media_desc ); memset ( stream,0,sizeof ( *stream ) ); proto = belle_sdp_media_get_protocol ( media ); stream->proto=SalProtoUnknown; if ( proto ) { if ( strcasecmp ( proto,"RTP/AVP" ) ==0 ) stream->proto=SalProtoRtpAvp; else if ( strcasecmp ( proto,"RTP/SAVP" ) ==0 ) { stream->proto=SalProtoRtpSavp; } } if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) { strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ),sizeof ( stream->rtp_addr ) ); } stream->rtp_port=belle_sdp_media_get_media_port ( media ); if ( stream->rtp_port > 0 ) desc->n_active_streams++; mtype = belle_sdp_media_get_media_type ( media ); 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 ); } if ( belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ) >0 ) { stream->bandwidth=belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ); } if ( belle_sdp_media_description_get_attribute ( media_desc,"sendrecv" ) ) { stream->dir=SalStreamSendRecv; } else if ( belle_sdp_media_description_get_attribute ( media_desc,"sendonly" ) ) { stream->dir=SalStreamSendOnly; } else if ( belle_sdp_media_description_get_attribute ( media_desc,"recvonly" ) ) { stream->dir=SalStreamRecvOnly; } else if ( belle_sdp_media_description_get_attribute ( media_desc,"inactive" ) ) { stream->dir=SalStreamInactive; } else { stream->dir=stream_dir; /*takes default value if not present*/ } /* for each payload type */ mime_params=belle_sdp_media_description_build_mime_parameters ( media_desc ); for ( mime_param_it=mime_params ; mime_param_it!=NULL ; mime_param_it=mime_param_it->next ) { mime_param=BELLE_SDP_MIME_PARAMETER ( mime_param_it->data ) pt=payload_type_new(); payload_type_set_number ( pt,belle_sdp_mime_parameter_get_media_format ( mime_param ) ); pt->clock_rate=belle_sdp_mime_parameter_get_rate ( mime_param ); pt->mime_type=ms_strdup ( belle_sdp_mime_parameter_get_type ( mime_param ) ); pt->channels=belle_sdp_mime_parameter_get_channel_count ( mime_param ); payload_type_set_send_fmtp ( pt,belle_sdp_mime_parameter_get_parameters ( mime_param ) ); stream->payloads=ms_list_append ( stream->payloads,pt ); stream->ptime=belle_sdp_mime_parameter_get_ptime ( mime_param ); ms_message ( "Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate, pt->send_fmtp ? pt->send_fmtp : "" ); } if ( mime_params ) belle_sip_list_free_with_data ( mime_params,belle_sip_object_unref ); /* Get media specific RTCP attribute */ stream->rtcp_port = stream->rtp_port + 1; snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), "%s", stream->rtp_addr); attribute=belle_sdp_media_description_get_attribute(media_desc,"rtcp"); if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){ char tmp[256]; int nb = sscanf(value, "%d IN IP4 %s", &stream->rtcp_port, tmp); if (nb == 1) { /* SDP rtcp attribute only contains the port */ } else if (nb == 2) { strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr)); } else { ms_warning("sdp has a strange a=rtcp line (%s) nb=%i", value, nb); } } /* read crypto lines if any */ if ( stream->proto == SalProtoRtpSavp ) { valid_count=0; memset ( &stream->crypto, 0, sizeof ( stream->crypto ) ); for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc ) ; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL; attribute_it=attribute_it->next ) { attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data ); if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) { nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s", &stream->crypto[valid_count].tag, tmp, tmp2 ); ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'", stream->crypto[valid_count].tag, tmp, tmp2 ); if ( nb == 3 ) { if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 ) stream->crypto[valid_count].algo = AES_128_SHA1_80; else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 ) stream->crypto[valid_count].algo = AES_128_SHA1_32; else { ms_warning ( "Failed to parse crypto-algo: '%s'", tmp ); stream->crypto[valid_count].algo = 0; } if ( stream->crypto[valid_count].algo ) { strncpy ( stream->crypto[valid_count].master_key, tmp2, 41 ); stream->crypto[valid_count].master_key[40] = '\0'; ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'", stream->crypto[valid_count].tag, tmp, stream->crypto[valid_count].master_key ); valid_count++; } } else { ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb ); } } } ms_message ( "Found: %d valid crypto lines", valid_count ); } /* Get ICE candidate attributes if any */ for (attribute_it = belle_sdp_media_description_get_attributes(media_desc); attribute_it != NULL; attribute_it=attribute_it->next) { const char *att_name; attribute=(belle_sdp_attribute_t*)attribute_it->data; att_name=belle_sdp_attribute_get_name(attribute); value=belle_sdp_attribute_get_value(attribute); if ((keywordcmp("candidate", att_name) == 0) && (value != NULL)) { SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates]; int nb = sscanf(value, "%s %u UDP %u %s %d typ %s raddr %s rport %d", candidate->foundation, &candidate->componentID, &candidate->priority, candidate->addr, &candidate->port, candidate->type, candidate->raddr, &candidate->rport); if ((nb == 6) || (nb == 8)) nb_ice_candidates++; else memset(candidate, 0, sizeof(*candidate)); } else if ((keywordcmp("remote-candidates", att_name) == 0) && (value != NULL)) { SalIceRemoteCandidate candidate; unsigned int componentID; int offset; const char *ptr = value; const char *endptr=value+strlen(ptr); while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) { if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) { SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1]; strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr)); remote_candidate->port = candidate.port; } ptr += offset; if (ptr<endptr){ if (ptr[offset] == ' ') ptr += 1; }else break; } } else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) { strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag)); } else if ((keywordcmp("ice-pwd", att_name) == 0) && (value != NULL)) { strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd)); } else if (keywordcmp("ice-mismatch", att_name) == 0) { stream->ice_mismatch = TRUE; } } desc->n_total_streams++; } return 0; }
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; } }