src/stun_udp.c

00001  /*
00002   The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
00003   Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014 
00015   You should have received a copy of the GNU Lesser General Public
00016   License along with this library; if not, write to the Free Software
00017   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 
00020 /* ====================================================================
00021  * The Vovida Software License, Version 1.0 
00022  * 
00023  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00024  * 
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions
00027  * are met:
00028  * 
00029  * 1. Redistributions of source code must retain the above copyright
00030  *    notice, this list of conditions and the following disclaimer.
00031  * 
00032  * 2. Redistributions in binary form must reproduce the above copyright
00033  *    notice, this list of conditions and the following disclaimer in
00034  *    the documentation and/or other materials provided with the
00035  *    distribution.
00036  * 
00037  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00038  *    and "Vovida Open Communication Application Library (VOCAL)" must
00039  *    not be used to endorse or promote products derived from this
00040  *    software without prior written permission. For written
00041  *    permission, please contact vocal@vovida.org.
00042  *
00043  * 4. Products derived from this software may not be called "VOCAL", nor
00044  *    may "VOCAL" appear in their name, without prior written
00045  *    permission of Vovida Networks, Inc.
00046  * 
00047  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00048  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00049  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00050  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00051  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00052  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00053  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00054  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00055  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00056  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00057  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00058  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00059  * DAMAGE.
00060  * 
00061  * ====================================================================
00062  * 
00063  * This software consists of voluntary contributions made by Vovida
00064  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00065  * Inc.  For more information on Vovida Networks, Inc., please see
00066  * <http://www.vovida.org/>.
00067  *
00068  */
00069 
00070 #include <stdlib.h>
00071 #include <string.h>
00072 #include <stdio.h>
00073 #if !defined(WIN32) && !defined(_WIN32_WCE)
00074 #include <sys/ioctl.h>
00075 #include <sys/socket.h>
00076 #include <sys/time.h>
00077 #include <sys/types.h> 
00078 #include <arpa/inet.h>
00079 #include <fcntl.h>
00080 #include <netdb.h>
00081 #include <netinet/in.h>
00082 #include <arpa/nameser.h>
00083 #include <resolv.h>
00084 #include <net/if.h>
00085 #endif
00086 #include <assert.h>
00087 
00088 #include <time.h>
00089 
00090 #if defined(WIN32) || defined(_WIN32_WCE)
00091 
00092 #include <winsock2.h>
00093 #include <stdlib.h>
00094 /* #include <io.h> */
00095 
00096 #else
00097 
00098 #include <arpa/inet.h>
00099 #include <stdlib.h>
00100 #include <unistd.h>
00101 #include <fcntl.h>
00102 #include <netinet/in.h>
00103 #include <sys/socket.h>
00104 #include <sys/types.h>
00105 #include <netdb.h>
00106 #include <string.h>
00107 #include <unistd.h>
00108 
00109 #endif
00110 
00111 #include <string.h>
00112 
00113 #include "ortp/stun_udp.h"
00114 #include "ortp/ortp.h"
00115 
00116 #if !defined(WIN32) && !defined(_WIN32_WCE)
00117 int getErrno() { return errno; }
00118 #else
00119 int getErrno() { return WSAGetLastError(); }
00120 #endif
00121 
00122 Socket
00123 openPort( unsigned short port, unsigned int interfaceIp, bool_t verbose )
00124 {
00125    struct sockaddr_in addr;
00126    Socket fd;
00127     
00128    fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00129    if ( fd == INVALID_SOCKET )
00130    {
00131           ortp_error("stun_udp: Could not create a UDP socket");
00132       return INVALID_SOCKET;
00133    }
00134    
00135    memset((char*) &(addr),0, sizeof((addr)));
00136    addr.sin_family = AF_INET;
00137    addr.sin_addr.s_addr = htonl(INADDR_ANY);
00138    addr.sin_port = htons(port);
00139     
00140    if ( (interfaceIp != 0) && 
00141         ( interfaceIp != 0x100007f ) )
00142    {
00143       addr.sin_addr.s_addr = htonl(interfaceIp);
00144       if (verbose )
00145       {
00146          ortp_message("Binding to interface 0x%lu\n",(unsigned long) htonl(interfaceIp));
00147       }
00148    }
00149         
00150    if ( bind( fd,(struct sockaddr*)&addr, sizeof(addr)) != 0 )
00151    {
00152       int e = getErrno();
00153         
00154       switch (e)
00155       {
00156          case 0:
00157          {
00158             ortp_error("stun_udp: Could not bind socket");;
00159             return INVALID_SOCKET;
00160          }
00161          case EADDRINUSE:
00162          {
00163             ortp_error("stun_udp: Port %i for receiving UDP is in use", port);
00164             return INVALID_SOCKET;
00165          }
00166          break;
00167          case EADDRNOTAVAIL:
00168          {
00169             if ( verbose ) 
00170             {
00171                ortp_error("stun_udp: Cannot assign requested address");
00172             }
00173             return INVALID_SOCKET;
00174          }
00175          break;
00176          default:
00177          {
00178 #if !defined(_WIN32_WCE)
00179                          ortp_error("stun_udp: Could not bind UDP receive port Error=%i %s",
00180                    e, strerror(e));
00181 #else
00182                          ortp_error("stun_udp: Could not bind UDP receive port Error=%i",
00183                    e);
00184 #endif
00185             return INVALID_SOCKET;
00186          }
00187          break;
00188       }
00189    }
00190    if ( verbose )
00191    {
00192            ortp_message("stun: opened port %i with fd %i\n", port, fd);
00193    }
00194    
00195    /* assert( fd != INVALID_SOCKET  ); */
00196         
00197    return fd;
00198 }
00199 
00200 
00201 bool_t 
00202 getMessage( Socket fd, char* buf, int* len,
00203             unsigned int* srcIp, unsigned short* srcPort,
00204             bool_t verbose)
00205 {
00206    /* assert( fd != INVALID_SOCKET ); */
00207         
00208    int originalSize = *len;
00209    struct sockaddr_in from;
00210    int fromLen = sizeof(from);
00211         
00212 
00213    int err;
00214    struct timeval tv;
00215    fd_set fdSet; 
00216 #if defined(WIN32) || defined(_WIN32_WCE)
00217    unsigned int fdSetSize;
00218 #else
00219    int fdSetSize;
00220 #endif
00221 
00222    if (originalSize <= 0)
00223    {
00224            return FALSE;
00225    }
00226 
00227    tv.tv_sec=1;
00228    tv.tv_usec=0; /* 150 ms */
00229    FD_ZERO(&fdSet); fdSetSize=0;
00230    FD_SET(fd,&fdSet); fdSetSize = fd+1;
00231 
00232    err = select(fdSetSize, &fdSet, NULL, NULL, &tv);
00233    if ( err == SOCKET_ERROR )
00234    {
00235       int e = getErrno();
00236       switch (e)
00237       {
00238          case ENOTSOCK:
00239             ortp_error("stun_udp: Error fd not a socket");
00240             break;
00241          case ECONNRESET:
00242             ortp_error("stun_udp: Error connection reset - host not reachable");
00243             break;
00244                                 
00245          default:
00246             ortp_error("stun_udp: Socket Error=%i", e);
00247       }
00248       return FALSE;
00249    }
00250 
00251     if (err==0)
00252     {
00253         ortp_error("stun_udp: Connection timeout with stun server!");
00254         *len = 0;
00255         return FALSE;
00256     }
00257 
00258     if (FD_ISSET (fd, &fdSet))
00259     {
00260         *len = recvfrom(fd,
00261                         buf,
00262                         originalSize,
00263                         0,
00264                         (struct sockaddr *)&from,
00265                         (socklen_t*)&fromLen);
00266                 
00267         if ( *len == SOCKET_ERROR )
00268         {
00269             int e = getErrno();
00270                         
00271             switch (e)
00272             {
00273                 case ENOTSOCK:
00274                     ortp_error("stun_udp: Error fd not a socket");
00275                     break;
00276                 case ECONNRESET:
00277                     ortp_error("stun_udp: Error connection reset - host not reachable");
00278                     break;
00279                                         
00280                 default:
00281                     ortp_error("stun_udp: Socket Error=%i", e);
00282             }
00283                         
00284             return FALSE;
00285         }
00286                 
00287         if ( *len < 0 )
00288         {
00289             ortp_error("stun_udp: socket closed? negative len");
00290             return FALSE;
00291         }
00292             
00293         if ( *len == 0 )
00294         {
00295             ortp_error("stun_udp: socket closed? zero len");
00296             return FALSE;
00297         }
00298             
00299         *srcPort = ntohs(from.sin_port);
00300         *srcIp = ntohl(from.sin_addr.s_addr);
00301                 
00302         if ( (*len)+1 >= originalSize )
00303         {
00304             if (verbose)
00305             {
00306                 ortp_error("stun_udp: Received a message that was too large");
00307             }
00308             return FALSE;
00309         }
00310         buf[*len]=0;
00311             
00312         return TRUE;
00313     }
00314     return FALSE;
00315 }
00316 
00317 
00318 bool_t 
00319 sendMessage( Socket fd, char* buf, int l, 
00320              unsigned int dstIp, unsigned short dstPort,
00321              bool_t verbose)
00322 {
00323    int s;
00324 
00325    if (fd == INVALID_SOCKET)
00326            return FALSE;
00327 
00328    if ( dstPort == 0 )
00329    {
00330       /* sending on a connected port */
00331       s = send(fd,buf,l,0);
00332    }
00333    else
00334    {
00335       struct sockaddr_in to;
00336       int toLen = sizeof(to);
00337       if (dstIp == 0)
00338           {
00339                   ortp_error("stun_udp: invalid IP provided (dstIP==0)");
00340                   return FALSE;
00341           }
00342 
00343       memset(&to,0,toLen);
00344         
00345       to.sin_family = AF_INET;
00346       to.sin_port = htons(dstPort);
00347       to.sin_addr.s_addr = htonl(dstIp);
00348         
00349       s = sendto(fd, buf, l, 0,(struct sockaddr*)&to, toLen);
00350    }
00351     
00352    if ( s == SOCKET_ERROR )
00353    {
00354       int e = getErrno();
00355       switch (e)
00356       {
00357          case ECONNREFUSED:
00358          case EHOSTDOWN:
00359          case EHOSTUNREACH:
00360          {
00361             /* quietly ignore this */
00362          }
00363          break;
00364          case EAFNOSUPPORT:
00365          {
00366             ortp_error("stun_udp: err EAFNOSUPPORT in send");
00367          }
00368          break;
00369          default:
00370          {
00371 #if !defined(_WIN32_WCE)
00372             ortp_error("stun_udp: err %i %s in send", e, strerror(e));
00373 #else
00374             ortp_error("stun_udp: err %i in send", e);
00375 #endif
00376          }
00377       }
00378       return FALSE;
00379    }
00380     
00381    if ( s == 0 )
00382    {
00383       ortp_error("stun_udp: no data sent in send");
00384       return FALSE;
00385    }
00386     
00387    if ( s != l )
00388    {
00389       if (verbose)
00390       {
00391          ortp_error("stun_udp: only %i out of %i bytes sent", s, l);
00392       }
00393       return FALSE;
00394    }
00395     
00396    return TRUE;
00397 }
00398 
00399 
00400 void
00401 initNetwork()
00402 {
00403 #if defined(WIN32) || defined(_WIN32_WCE)
00404    WORD wVersionRequested = MAKEWORD( 2, 2 );
00405    WSADATA wsaData;
00406    int err;
00407         
00408    err = WSAStartup( wVersionRequested, &wsaData );
00409    if ( err != 0 ) 
00410    {
00411       /* could not find a usable WinSock DLL */
00412       ortp_error("stun_udp: Could not load winsock");
00413    }
00414     
00415    /* Confirm that the WinSock DLL supports 2.2.*/
00416    /* Note that if the DLL supports versions greater    */
00417    /* than 2.2 in addition to 2.2, it will still return */
00418    /* 2.2 in wVersion since that is the version we      */
00419    /* requested.                                        */
00420     
00421    if ( LOBYTE( wsaData.wVersion ) != 2 ||
00422         HIBYTE( wsaData.wVersion ) != 2 ) 
00423    {
00424       /* Tell the user that we could not find a usable */
00425       /* WinSock DLL.                                  */
00426       WSACleanup( );
00427       ortp_error("stun_udp: Wrong winsock (!= 2.2) version");
00428    }    
00429 #endif
00430 }
00431 
00432 
00433 /* ====================================================================
00434  * The Vovida Software License, Version 1.0 
00435  * 
00436  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00437  * 
00438  * Redistribution and use in source and binary forms, with or without
00439  * modification, are permitted provided that the following conditions
00440  * are met:
00441  * 
00442  * 1. Redistributions of source code must retain the above copyright
00443  *    notice, this list of conditions and the following disclaimer.
00444  * 
00445  * 2. Redistributions in binary form must reproduce the above copyright
00446  *    notice, this list of conditions and the following disclaimer in
00447  *    the documentation and/or other materials provided with the
00448  *    distribution.
00449  * 
00450  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00451  *    and "Vovida Open Communication Application Library (VOCAL)" must
00452  *    not be used to endorse or promote products derived from this
00453  *    software without prior written permission. For written
00454  *    permission, please contact vocal@vovida.org.
00455  *
00456  * 4. Products derived from this software may not be called "VOCAL", nor
00457  *    may "VOCAL" appear in their name, without prior written
00458  *    permission of Vovida Networks, Inc.
00459  * 
00460  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00461  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00462  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00463  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00464  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00465  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00466  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00467  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00468  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00469  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00470  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00471  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00472  * DAMAGE.
00473  * 
00474  * ====================================================================
00475  * 
00476  * This software consists of voluntary contributions made by Vovida
00477  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00478  * Inc.  For more information on Vovida Networks, Inc., please see
00479  * <http://www.vovida.org/>.
00480  *
00481  */
00482 
00483 /* Local Variables:
00484    mode:c
00485    c-file-style:"ellemtel"
00486    c-file-offsets:((case-label . +))
00487    indent-tabs-mode:nil
00488    End:
00489 */

Generated on Thu Feb 14 16:10:27 2008 for oRTP by  doxygen 1.5.4