]> sjero.net Git - linphone/blob - coreapi/TunnelManager.cc
Avoid buffer overflow in console commands
[linphone] / coreapi / TunnelManager.cc
1 /*
2  *  C Implementation: tunnel
3  *
4  * Description: 
5  *
6  *
7  * Author: Simon Morlat <simon.morlat@linphone.org>, (C) 2009
8  *
9  * Copyright (C) 2010  Belledonne Comunications, Grenoble, France
10  *
11  */
12
13
14 #include "TunnelManager.hh"
15
16 #include "ortp/rtpsession.h"
17 #include "linphonecore.h"
18 #include "linphonecore_utils.h"
19 #include "eXosip2/eXosip_transport_hook.h"
20 #include "tunnel/udp_mirror.hh"
21
22 #ifdef ANDROID
23 #include <android/log.h>
24 #endif
25
26
27 using namespace belledonnecomm;
28
29 Mutex TunnelManager::sMutex;
30
31 int TunnelManager::eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata){
32         TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
33         int err;
34         sMutex.lock();
35         if (lTunnelMgr->mSipSocket==NULL){
36                 sMutex.unlock();
37                 return len;//let ignore the error
38         }
39         err=lTunnelMgr->mSipSocket->sendto(buf,len,to,tolen);
40         sMutex.unlock();
41         return err;
42 }
43
44 int TunnelManager::eXosipRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen,void* userdata){
45         TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
46         int err;
47         sMutex.lock();
48         if (lTunnelMgr->mSipSocket==NULL){
49                 sMutex.unlock();
50                 return 0;//let ignore the error
51         }
52         err=lTunnelMgr->mSipSocket->recvfrom(buf,len,from,*fromlen);
53         sMutex.unlock();
54         return err;
55 }
56
57 int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3, struct timeval *tv,void* userdata){
58         struct timeval begin,cur;
59         TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
60         if (tv!=0 && tv->tv_sec){
61                 /*this is the select from udp.c, the one that is interesting to us*/
62                 NativeSocket udp_fd=(NativeSocket)eXosip_get_udp_socket();
63                 NativeSocket controlfd=(NativeSocket)eXosip_get_control_fd();
64
65                 FD_ZERO(s1);            
66                 gettimeofday(&begin,NULL);
67                 do{
68                         struct timeval abit;
69
70                         abit.tv_sec=0;
71                         abit.tv_usec=20000;
72                         sMutex.lock();
73                         if (lTunnelMgr->mSipSocket!=NULL){
74                                 if (lTunnelMgr->mSipSocket->hasData()) {
75                                         sMutex.unlock();
76                                         /* we make exosip believe that it has udp data to read*/
77                                         FD_SET(udp_fd,s1);
78                                         return 1;
79                                 }
80                         }
81                         sMutex.unlock();
82                         gettimeofday(&cur,NULL);
83                         if (cur.tv_sec-begin.tv_sec>tv->tv_sec) {
84                                 FD_SET(controlfd,s1);
85                                 FD_SET(udp_fd,s1);
86                                 return 0;
87                         }
88                         FD_ZERO(s1);
89                         FD_SET(controlfd,s1);
90                         if (select(max_fds,s1,s2,s3,&abit)==1) {
91                                 return 1;
92                         }
93                 }while(1);
94                 
95         }else{
96                 /*select called from other places, only the control fd is present */
97                 return select(max_fds,s1,s2,s3,tv);
98         }
99 }
100
101
102 void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
103         addServer(ip,port);
104         mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay));
105 }
106
107 void TunnelManager::addServer(const char *ip, int port) {
108         mServerAddrs.push_back(ServerAddr(ip,port));
109         if (mTunnelClient) mTunnelClient->addServer(ip,port);
110 }
111
112 void TunnelManager::cleanServers() {
113         mServerAddrs.clear();
114
115         UdpMirrorClientList::iterator it;
116         mAutoDetectStarted=false;
117         for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) {
118                 UdpMirrorClient& s=*it++;
119                 s.stop();
120         }
121         mUdpMirrorClients.clear();
122         if (mTunnelClient) mTunnelClient->cleanServers();
123 }
124
125 void TunnelManager::reconnect(){
126         if (mTunnelClient)
127                 mTunnelClient->reconnect();
128 }
129
130 void TunnelManager::setCallback(StateCallback cb, void *userdata) {
131         mCallback=cb;
132         mCallbackData=userdata;
133 }
134
135 static void sCloseRtpTransport(RtpTransport *t, void *userData){
136         TunnelSocket *s=(TunnelSocket*)userData;
137         TunnelManager *manager=(TunnelManager*)s->getUserPointer();
138         manager->closeRtpTransport(t, s);
139 }
140 void TunnelManager::closeRtpTransport(RtpTransport *t, TunnelSocket *s){
141         mTunnelClient->closeSocket(s);
142         ms_free(t);
143 }
144
145 static RtpTransport *sCreateRtpTransport(void* userData, int port){
146         return ((TunnelManager *) userData)->createRtpTransport(port);
147 }
148
149 RtpTransport *TunnelManager::createRtpTransport(int port){
150         TunnelSocket *socket=mTunnelClient->createSocket(port);
151         socket->setUserPointer(this);
152         RtpTransport *t=ms_new0(RtpTransport,1);
153         t->t_getsocket=NULL;
154         t->t_recvfrom=customRecvfrom;
155         t->t_sendto=customSendto;
156         t->t_close=sCloseRtpTransport;
157         t->data=socket;
158         return t;
159 }
160
161 void TunnelManager::start() {
162         if (!mTunnelClient) {
163                 mTunnelClient = new TunnelClient();
164                 mTunnelClient->setCallback((StateCallback)tunnelCallback,this);
165                 list<ServerAddr>::iterator it;
166                 for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
167                         const ServerAddr &addr=*it;
168                         mTunnelClient->addServer(addr.mAddr.c_str(), addr.mPort);
169                 }
170                 mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
171         }
172         mTunnelClient->start();
173
174         if (mSipSocket == NULL) mSipSocket =mTunnelClient->createSocket(5060);
175 }
176
177 bool TunnelManager::isStarted() {
178         return mTunnelClient != 0 && mTunnelClient->isStarted();
179 }
180
181 bool TunnelManager::isReady() const {
182         return mTunnelClient && mTunnelClient->isReady();
183 }
184
185 int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
186         int size;
187         msgpullup(msg,-1);
188         size=msgdsize(msg);
189         ((TunnelSocket*)t->data)->sendto(msg->b_rptr,size,to,tolen);
190         return size;
191 }
192
193 int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen){
194         int err=((TunnelSocket*)t->data)->recvfrom(msg->b_wptr,msg->b_datap->db_lim-msg->b_datap->db_base,from,*fromlen);
195         if (err>0) return err;
196         return 0;
197 }
198
199
200 TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
201 ,mCore(lc)
202 ,mSipSocket(NULL)
203 ,mCallback(NULL)
204 ,mEnabled(false)
205 ,mTunnelClient(NULL)
206 ,mAutoDetectStarted(false)
207 ,mHttpProxyPort(0){
208
209         mExosipTransport.data=this;
210         mExosipTransport.recvfrom=eXosipRecvfrom;
211         mExosipTransport.sendto=eXosipSendto;
212         mExosipTransport.select=eXosipSelect;
213         mStateChanged=false;
214         linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
215         mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
216         mTransportFactories.audio_rtcp_func_data=this;
217         mTransportFactories.audio_rtp_func=sCreateRtpTransport;
218         mTransportFactories.audio_rtp_func_data=this;
219         mTransportFactories.video_rtcp_func=sCreateRtpTransport;
220         mTransportFactories.video_rtcp_func_data=this;
221         mTransportFactories.video_rtp_func=sCreateRtpTransport;
222         mTransportFactories.video_rtp_func_data=this;
223 }
224
225 TunnelManager::~TunnelManager(){
226         stopClient();
227 }
228
229 void TunnelManager::stopClient(){
230         eXosip_transport_hook_register(NULL);
231         if (mSipSocket != NULL){
232                 sMutex.lock();
233                 mTunnelClient->closeSocket(mSipSocket);
234                 mSipSocket = NULL;
235                 sMutex.unlock();
236         }
237         if (mTunnelClient){
238                 delete mTunnelClient;
239                 mTunnelClient=NULL;
240         }
241 }
242
243 void TunnelManager::processTunnelEvent(){
244         LinphoneProxyConfig* lProxy;
245         linphone_core_get_default_proxy(mCore, &lProxy);
246
247         if (mEnabled && mTunnelClient->isReady()){
248                 ms_message("Tunnel is up, registering now");            
249                 linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
250                 eXosip_transport_hook_register(&mExosipTransport);
251                 //force transport to udp
252                 LCSipTransports lTransport;
253                 
254                 lTransport.udp_port=15060;
255                 lTransport.tcp_port=0;
256                 lTransport.tls_port=0;
257                 lTransport.dtls_port=0;
258                 
259                 linphone_core_set_sip_transports(mCore, &lTransport);           
260                 //register
261                 if (lProxy) {
262                         linphone_proxy_config_done(lProxy);
263                 }
264         }else if (mEnabled && !mTunnelClient->isReady()){
265                 /* we got disconnected from the tunnel */
266                 if (lProxy && linphone_proxy_config_is_registered(lProxy)) {
267                         /*forces de-registration so that we register again when the tunnel is up*/
268                         linphone_proxy_config_edit(lProxy);
269                         linphone_core_iterate(mCore);
270                 }
271         }
272 }
273
274 void TunnelManager::waitUnRegistration(){
275         LinphoneProxyConfig* lProxy;
276         linphone_core_get_default_proxy(mCore, &lProxy);
277         if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) {
278                 int i;
279                 linphone_proxy_config_edit(lProxy);
280                 //make sure unregister is sent and authenticated
281                 do{
282                         linphone_core_iterate(mCore);
283                         ms_usleep(20000);
284                         if (i>100){
285                                 ms_message("tunnel: timeout for unregistration expired, giving up");
286                                 break;
287                         }
288                         i++;
289                 }while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared);
290         }       
291 }
292
293 void TunnelManager::enable(bool isEnable) {
294         ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
295         if (isEnable && !mEnabled){
296                 mEnabled=true;
297                 //1 save transport 
298                 linphone_core_get_sip_transports(mCore, &mRegularTransport);
299                 //2 unregister
300                 waitUnRegistration();
301                 //3 insert tunnel
302                 start();
303         }else if (!isEnable && mEnabled){
304                 //1 unregister
305                 waitUnRegistration();
306                 
307                 mEnabled=false;
308                 stopClient();
309                 
310                 linphone_core_set_rtp_transport_factories(mCore,NULL);
311
312                 eXosip_transport_hook_register(NULL);
313                 //Restore transport
314                 linphone_core_set_sip_transports(mCore, &mRegularTransport);
315                 //register
316                 LinphoneProxyConfig* lProxy;
317                 linphone_core_get_default_proxy(mCore, &lProxy);
318                 if (lProxy) {
319                         linphone_proxy_config_done(lProxy);
320                 }
321
322         }
323 }
324
325 void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
326         zis->mStateChanged=true;
327 }
328
329 /*invoked from linphone_core_iterate() */
330 void TunnelManager::sOnIterate(TunnelManager *zis){
331         if (zis->mStateChanged){
332                 zis->mStateChanged=false;
333                 zis->processTunnelEvent();
334         }
335 }
336
337 #ifdef ANDROID
338 static void linphone_android_log_handler(int lev, const char *fmt, va_list args){
339         int prio;
340         switch(lev){
341         case TUNNEL_DEBUG:      prio = ANDROID_LOG_DEBUG;       break;
342         case TUNNEL_INFO:       prio = ANDROID_LOG_INFO;        break;
343         case TUNNEL_NOTICE:     prio = ANDROID_LOG_INFO;        break;
344         case TUNNEL_WARN:       prio = ANDROID_LOG_WARN;        break;
345         case TUNNEL_ERROR:      prio = ANDROID_LOG_ERROR;       break;
346         default:                        prio = ANDROID_LOG_DEFAULT;     break;
347         }
348         __android_log_vprint(prio, LOG_DOMAIN, fmt, args);
349 }
350 #endif /*ANDROID*/
351
352 void TunnelManager::enableLogs(bool value) {
353         enableLogs(value,NULL);
354 }
355
356 void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
357         if (logHandler != NULL) SetLogHandler(logHandler);
358 #ifdef ANDROID
359         else SetLogHandler(linphone_android_log_handler);
360 #else
361         else SetLogHandler(default_log_handler);
362 #endif
363
364         if (isEnabled) {
365                 SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN|TUNNEL_INFO);
366         } else {
367                 SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN);
368         }
369 }
370         
371
372 bool TunnelManager::isEnabled() {
373         return mEnabled;
374 }
375 void TunnelManager::UdpMirrorClientListener(bool isUdpAvailable, void* data) {
376         TunnelManager* thiz = (TunnelManager*)data;
377         if (isUdpAvailable) {
378                 LOGI("Tunnel is not required, disabling");
379                 thiz->enable(false);
380                 thiz->mAutoDetectStarted = false;
381         } else {
382                 if (++thiz->mCurrentUdpMirrorClient !=thiz->mUdpMirrorClients.end()) {
383                         //1 enable tunnable but also try backup server
384                         LOGI("Tunnel is required, enabling; Trying backup udp mirror");
385                         
386                         UdpMirrorClient &lUdpMirrorClient=*thiz->mCurrentUdpMirrorClient;
387                         lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)thiz);
388                 } else {
389                         LOGI("Tunnel is required, enabling; no backup udp mirror available");
390                         thiz->mAutoDetectStarted = false;
391                 }
392                 thiz->enable(true);
393         }
394         return;
395 }
396
397 void TunnelManager::autoDetect() {
398         // first check if udp mirrors was provisionned
399         if (mUdpMirrorClients.empty()) {
400                 LOGE("No UDP mirror server configured aborting auto detection");
401                 return;
402         }
403         if (mAutoDetectStarted) {
404                 LOGE("auto detection already in progress, restarting");
405                 (*mCurrentUdpMirrorClient).stop();
406         }
407         mAutoDetectStarted=true;
408         mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
409         UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
410         lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this);
411         
412 }
413
414 void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
415         mHttpUserName=username?username:"";
416         mHttpPasswd=passwd?passwd:"";
417         if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd);
418 }
419
420 void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){
421         mHttpUserName=username?username:"";
422         mHttpPasswd=passwd?passwd:"";
423         mHttpProxyPort=(port>0) ? port : 0;
424         mHttpProxyHost=host ? host : "";
425         if (mTunnelClient) mTunnelClient->setHttpProxy(host, port, username, passwd);
426 }
427
428 LinphoneCore *TunnelManager::getLinphoneCore(){
429         return mCore;
430 }