void eXosip_get_localip_from_via(osip_message_t *mesg,char **locip){ osip_via_t *via=NULL; char *host; via=(osip_via_t*)osip_list_get(mesg->vias,0); if (via==NULL) { host="15.128.128.93"; eXosip_trace(OSIP_ERROR,("Could not get via:%s")); }else host=via->host; eXosip_get_localip_for(host,locip); }
/* 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 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 eXosip_trace(OSIP_WARNING,("sdp has a strange a=ptime line (%s) ",attr->a_att_value)); } } return 0; }
/* return the value of attr "field" for payload pt at line pos (field=rtpmap,fmtp...)*/ 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 eXosip_trace(OSIP_WARNING,("sdp has a strange a= line (%s) nb=%i",attr->a_att_value,nb)); } } return NULL; }
void eXosip_get_localip_for(char *address_to_reach,char **loc){ int err,tmp; struct addrinfo hints; struct addrinfo *res=NULL; struct sockaddr_storage addr; int sock; #ifdef __APPLE_CC__ int s; #else socklen_t s; #endif if (eXosip.forced_localip){ *loc=osip_strdup(eXosip.localip); return; } *loc=osip_malloc(MAXHOSTNAMELEN); strcpy(*loc,"127.0.0.1"); /* always fallback to local loopback */ memset(&hints,0,sizeof(hints)); hints.ai_family=PF_UNSPEC; hints.ai_socktype=SOCK_DGRAM; /*hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME;*/ err=getaddrinfo(address_to_reach,"5060",&hints,&res); if (err!=0){ eXosip_trace(OSIP_ERROR,("Error in getaddrinfo for %s: %s\n",address_to_reach,gai_strerror(err))); return ; } if (res==NULL){ eXosip_trace(OSIP_ERROR,("getaddrinfo reported nothing !")); abort(); return ; } sock=socket(res->ai_family,SOCK_DGRAM,0); tmp=1; err=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&tmp,sizeof(int)); if (err<0){ eXosip_trace(OSIP_ERROR,("Error in setsockopt: %s\n",strerror(errno))); abort(); return ; } err=connect(sock,res->ai_addr,res->ai_addrlen); if (err<0) { eXosip_trace(OSIP_ERROR,("Error in connect: %s\n",strerror(errno))); abort(); return ; } freeaddrinfo(res); res=NULL; s=sizeof(addr); err=getsockname(sock,(struct sockaddr*)&addr,&s); if (err!=0) { eXosip_trace(OSIP_ERROR,("Error in getsockname: %s\n",strerror(errno))); close(sock); return ; } err=getnameinfo((struct sockaddr *)&addr,s,*loc,MAXHOSTNAMELEN,NULL,0,NI_NUMERICHOST); if (err!=0){ eXosip_trace(OSIP_ERROR,("getnameinfo error:%s",strerror(errno))); abort(); return ; } close(sock); eXosip_trace(OSIP_INFO1,("Outgoing interface to reach %s is %s.\n",address_to_reach,*loc)); return ; }
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; } }