📄 ice.c
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#if !defined(WIN32) && !defined(_WIN32_WCE)#ifdef __APPLE__#include <sys/types.h>#endif#include <sys/socket.h>#include <netdb.h>#endif#include "mediastreamer2/ice.h"#include "mediastreamer2/mscommon.h"static void ice_sendtest( Socket myFd, StunAddress4 *dest, const StunAtrString *username, const StunAtrString *password, int testNum, bool_t verbose , UInt128 *tid);static void ice_sendtest( Socket myFd, StunAddress4 *dest, const StunAtrString *username, const StunAtrString *password, int testNum, bool_t verbose , UInt128 *tid){ bool_t changePort=FALSE; bool_t changeIP=FALSE; bool_t discard=FALSE; StunMessage req; char buf[STUN_MAX_MESSAGE_SIZE]; int len = STUN_MAX_MESSAGE_SIZE; switch (testNum) { case 1: case 10: case 11: break; case 2: /* changePort=TRUE; */ changeIP=TRUE; break; case 3: changePort=TRUE; break; case 4: changeIP=TRUE; break; case 5: discard=TRUE; break; default: printf("Test %i is unkown\n", testNum); return ; /* error */ } memset(&req, 0, sizeof(StunMessage)); stunBuildReqSimple( &req, username, changePort , changeIP , testNum ); len = stunEncodeMessage( &req, buf, len, password,verbose ); memcpy(tid , &(req.msgHdr.id), sizeof(req.msgHdr.id)); sendMessage( myFd, buf, len, dest->addr, dest->port, verbose ); }int ice_sound_send_stun_request(RtpSession *session, struct CandidatePair *remote_candidates, int round){ int roll=250;#if 0 /* in "passive" mode (UA not behind a NATor behind a full cone NAT), wait a few delay before sending the first STUN request: this help to traverse */ if (session->setup_passive>0) { return 0; }#endif if (remote_candidates==NULL) return 0; if (round>500) roll=2*roll; if (round%roll==50) { int pos;#if 0 /* do this only with application that support this */ if (osip_strncasecmp(remote_useragent, "linphone/", 8)!=0) { /* use stun only with linphone to linphone softphone */ return 0; }#endif for (pos=0;pos<10 && remote_candidates[pos].remote_candidate.ipaddr[0]!='\0';pos++) { int media_socket = rtp_session_get_rtp_socket(session); StunAddress4 stunServerAddr; StunAtrString username; StunAtrString password; bool_t res; int pad_size; struct CandidatePair *cand_pair = &remote_candidates[pos]; username.sizeValue = 0; password.sizeValue = 0; /* set username to L3:1:R2:1 */ snprintf(username.value, sizeof(username.value), "%s:%i:%s:%i", cand_pair->local_candidate.candidate_id, 1, cand_pair->remote_candidate.candidate_id, 1); username.sizeValue = (UInt16)strlen(username.value); pad_size = username.sizeValue % 4; username.value[username.sizeValue]='\0'; username.value[username.sizeValue+1]='\0'; username.value[username.sizeValue+2]='\0'; username.value[username.sizeValue+3]='\0'; username.sizeValue = username.sizeValue + 4 - pad_size; snprintf(password.value, sizeof(password.value), "%s", cand_pair->remote_candidate.password); password.sizeValue = (UInt16)strlen(password.value);#if 0 pad_size = password.sizeValue%4; password.value[password.sizeValue]='\0'; password.value[password.sizeValue+1]='\0'; password.value[password.sizeValue+2]='\0'; password.value[password.sizeValue+3]='\0'; password.sizeValue = password.sizeValue + pad_size;#endif res = stunParseServerName(cand_pair->remote_candidate.ipaddr, &stunServerAddr); if ( res == TRUE ) { stunServerAddr.port = cand_pair->remote_candidate.port; ice_sendtest(media_socket, &stunServerAddr, &username, &password, 1, 0/*FALSE*/, &(cand_pair->tid)); } } } return 0;}static int_ice_get_localip_for (struct sockaddr_storage *saddr, size_t saddr_len, char *loc, int size){ int err, tmp; int sock; struct sockaddr_storage addr; socklen_t addr_len; strcpy (loc, "127.0.0.1"); /* always fallback to local loopback */ sock = socket (saddr->ss_family, SOCK_DGRAM, 0); tmp = 1; err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &tmp, sizeof (int)); if (err < 0) { ms_error("ice.c: Error in setsockopt"); closesocket (sock); return -1; } err = connect (sock, (struct sockaddr*)saddr, saddr_len); if (err < 0) { ms_error("ice.c: Error in connect"); closesocket (sock); return -1; } addr_len = sizeof (addr); err = getsockname (sock, (struct sockaddr *) &addr, (socklen_t*)&addr_len); if (err != 0) { ms_error("ice.c: Error in getsockname"); closesocket (sock); return -1; } err = getnameinfo ((struct sockaddr *) &addr, addr_len, loc, size, NULL, 0, NI_NUMERICHOST); if (err != 0) { ms_error("ice.c: Error in getnameinfo"); closesocket (sock); return -1; } closesocket (sock); /* ms_message("ice.c: Outgoing interface for sending STUN answer is %s", loc); */ return 0;}int ice_process_stun_message(RtpSession *session, struct CandidatePair *remote_candidates, OrtpEvent *evt){ int switch_to_address = -1; StunMessage msg; bool_t res; int already_worked_once=-1; OrtpEventData *evt_data = ortp_event_get_data(evt); mblk_t *mp = evt_data->packet; struct sockaddr_in *udp_remote; char src6host[NI_MAXHOST]; int recvport = 0; int i; udp_remote = (struct sockaddr_in*)&evt_data->ep->addr; memset( &msg, 0 , sizeof(msg) ); res = stunParseMessage((char*)mp->b_rptr, mp->b_wptr-mp->b_rptr, &msg, 0); if (!res) { ms_error("ice.c: Malformed STUN packet."); return -1; } memset (src6host, 0, sizeof (src6host)); { struct sockaddr_storage *aaddr = (struct sockaddr_storage *)&evt_data->ep->addr; if (aaddr->ss_family==AF_INET) recvport = ntohs (((struct sockaddr_in *) udp_remote)->sin_port); else recvport = ntohs (((struct sockaddr_in6 *) &evt_data->ep->addr)->sin6_port); } i = getnameinfo ((struct sockaddr*)&evt_data->ep->addr, evt_data->ep->addrlen, src6host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (i != 0) { ms_error("ice.c: Error with getnameinfo"); } else { if (msg.msgHdr.msgType == BindRequestMsg) ms_message("ice.c: Request received from: %s:%i", src6host, recvport); else ms_message("ice.c: Answer received from: %s:%i", src6host, recvport); } if (remote_candidates!=NULL) { int pos; for (pos=0;pos<10 && remote_candidates[pos].remote_candidate.ipaddr[0]!='\0';pos++) { struct CandidatePair *cand_pair = &remote_candidates[pos];#ifdef RESTRICTIVE_ICE if (cand_pair->connectivity_check == VALID ||cand_pair->connectivity_check == RECV_VALID) { already_worked_once=pos; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -