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 
00115 #if !defined(WIN32) && !defined(_WIN32_WCE)
00116 int getErrno() { return errno; }
00117 #else
00118 int getErrno() { return WSAGetLastError(); }
00119 #endif
00120 
00121 Socket
00122 openPort( unsigned short port, unsigned int interfaceIp, bool_t verbose )
00123 {
00124    struct sockaddr_in addr;
00125    Socket fd;
00126     
00127    fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00128    if ( fd == INVALID_SOCKET )
00129    {
00130       printf("Could not create a UDP socket:\n");
00131       return INVALID_SOCKET;
00132    }
00133    
00134    memset((char*) &(addr),0, sizeof((addr)));
00135    addr.sin_family = AF_INET;
00136    addr.sin_addr.s_addr = htonl(INADDR_ANY);
00137    addr.sin_port = htons(port);
00138     
00139    if ( (interfaceIp != 0) && 
00140         ( interfaceIp != 0x100007f ) )
00141    {
00142       addr.sin_addr.s_addr = htonl(interfaceIp);
00143       if (verbose )
00144       {
00145          printf("Binding to interface 0x%lu\n",(unsigned long) htonl(interfaceIp));
00146       }
00147    }
00148         
00149    if ( bind( fd,(struct sockaddr*)&addr, sizeof(addr)) != 0 )
00150    {
00151       int e = getErrno();
00152         
00153       switch (e)
00154       {
00155          case 0:
00156          {
00157             printf("Could not bind socket\n");;
00158             return INVALID_SOCKET;
00159          }
00160          case EADDRINUSE:
00161          {
00162             printf("Port %i for receiving UDP is in use\n", port);
00163             return INVALID_SOCKET;
00164          }
00165          break;
00166          case EADDRNOTAVAIL:
00167          {
00168             if ( verbose ) 
00169             {
00170                printf("Cannot assign requested address\n");
00171             }
00172             return INVALID_SOCKET;
00173          }
00174          break;
00175          default:
00176          {
00177 #if !defined(_WIN32_WCE)
00178                          printf("Could not bind UDP receive port Error=%i %s\n",
00179                    e, strerror(e));
00180 #else
00181                          printf("Could not bind UDP receive port Error=%i\n",
00182                    e);
00183 #endif
00184             return INVALID_SOCKET;
00185          }
00186          break;
00187       }
00188    }
00189    if ( verbose )
00190    {
00191       printf("Opened port %i with fd %i\n", port, fd);
00192    }
00193    
00194    /* assert( fd != INVALID_SOCKET  ); */
00195         
00196    return fd;
00197 }
00198 
00199 
00200 bool_t 
00201 getMessage( Socket fd, char* buf, int* len,
00202             unsigned int* srcIp, unsigned short* srcPort,
00203             bool_t verbose)
00204 {
00205    /* assert( fd != INVALID_SOCKET ); */
00206         
00207    int originalSize = *len;
00208    struct sockaddr_in from;
00209    int fromLen = sizeof(from);
00210         
00211 
00212    int err;
00213    struct timeval tv;
00214    fd_set fdSet; 
00215 #if defined(WIN32) || defined(_WIN32_WCE)
00216    unsigned int fdSetSize;
00217 #else
00218    int fdSetSize;
00219 #endif
00220 
00221    assert( originalSize > 0 );
00222 
00223    tv.tv_sec=1;
00224    tv.tv_usec=0; /* 150 ms */
00225    FD_ZERO(&fdSet); fdSetSize=0;
00226    FD_SET(fd,&fdSet); fdSetSize = fd+1;
00227 
00228    err = select(fdSetSize, &fdSet, NULL, NULL, &tv);
00229    if ( err == SOCKET_ERROR )
00230    {
00231       int e = getErrno();
00232       switch (e)
00233       {
00234          case ENOTSOCK:
00235             printf("Error fd not a socket\n");
00236             break;
00237          case ECONNRESET:
00238             printf("Error connection reset - host not reachable\n");
00239             break;
00240                                 
00241          default:
00242             printf("Socket Error=%i\n", e);
00243       }
00244       return FALSE;
00245    }
00246 
00247     if (err==0)
00248     {
00249         printf("Connection timeout with stun server!\n");
00250         *len = 0;
00251         return FALSE;
00252     }
00253 
00254     if (FD_ISSET (fd, &fdSet))
00255     {
00256         *len = recvfrom(fd,
00257                         buf,
00258                         originalSize,
00259                         0,
00260                         (struct sockaddr *)&from,
00261                         (socklen_t*)&fromLen);
00262                 
00263         if ( *len == SOCKET_ERROR )
00264         {
00265             int e = getErrno();
00266                         
00267             switch (e)
00268             {
00269                 case ENOTSOCK:
00270                     printf("Error fd not a socket\n");
00271                     break;
00272                 case ECONNRESET:
00273                     printf("Error connection reset - host not reachable\n");
00274                     break;
00275                                         
00276                 default:
00277                     printf("Socket Error=%i\n", e);
00278             }
00279                         
00280             return FALSE;
00281         }
00282                 
00283         if ( *len < 0 )
00284         {
00285             printf("socket closed? negative len\n");
00286             return FALSE;
00287         }
00288             
00289         if ( *len == 0 )
00290         {
00291             printf("socket closed? zero len\n");
00292             return FALSE;
00293         }
00294             
00295         *srcPort = ntohs(from.sin_port);
00296         *srcIp = ntohl(from.sin_addr.s_addr);
00297                 
00298         if ( (*len)+1 >= originalSize )
00299         {
00300             if (verbose)
00301             {
00302                 printf("Received a message that was too large\n");
00303             }
00304             return FALSE;
00305         }
00306         buf[*len]=0;
00307             
00308         return TRUE;
00309     }
00310     return FALSE;
00311 }
00312 
00313 
00314 bool_t 
00315 sendMessage( Socket fd, char* buf, int l, 
00316              unsigned int dstIp, unsigned short dstPort,
00317              bool_t verbose)
00318 {
00319    int s;
00320    assert( fd != INVALID_SOCKET );
00321 
00322    if ( dstPort == 0 )
00323    {
00324       /* sending on a connected port */
00325       assert( dstIp == 0 );
00326                 
00327       s = send(fd,buf,l,0);
00328    }
00329    else
00330    {
00331       struct sockaddr_in to;
00332       int toLen = sizeof(to);
00333       assert( dstIp != 0 );
00334       assert( dstPort != 0 );
00335         
00336 
00337       memset(&to,0,toLen);
00338         
00339       to.sin_family = AF_INET;
00340       to.sin_port = htons(dstPort);
00341       to.sin_addr.s_addr = htonl(dstIp);
00342         
00343       s = sendto(fd, buf, l, 0,(struct sockaddr*)&to, toLen);
00344    }
00345     
00346    if ( s == SOCKET_ERROR )
00347    {
00348       int e = getErrno();
00349       switch (e)
00350       {
00351          case ECONNREFUSED:
00352          case EHOSTDOWN:
00353          case EHOSTUNREACH:
00354          {
00355             /* quietly ignore this */
00356          }
00357          break;
00358          case EAFNOSUPPORT:
00359          {
00360             printf("err EAFNOSUPPORT in send\n");
00361          }
00362          break;
00363          default:
00364          {
00365 #if !defined(_WIN32_WCE)
00366             printf("err %i %s in send\n", e, strerror(e));
00367 #else
00368             printf("err %i in send\n", e);
00369 #endif
00370          }
00371       }
00372       return FALSE;
00373    }
00374     
00375    if ( s == 0 )
00376    {
00377       printf("no data sent in send\n");
00378       return FALSE;
00379    }
00380     
00381    if ( s != l )
00382    {
00383       if (verbose)
00384       {
00385          printf("only %i out of %i bytes sent\n", s, l);
00386       }
00387       return FALSE;
00388    }
00389     
00390    return TRUE;
00391 }
00392 
00393 
00394 void
00395 initNetwork()
00396 {
00397 #if defined(WIN32) || defined(_WIN32_WCE)
00398    WORD wVersionRequested = MAKEWORD( 2, 2 );
00399    WSADATA wsaData;
00400    int err;
00401         
00402    err = WSAStartup( wVersionRequested, &wsaData );
00403    if ( err != 0 ) 
00404    {
00405       /* could not find a usable WinSock DLL */
00406       printf("Could not load winsock\n");
00407       assert(0); /* is this is failing, try a different version that 2.2, 1.0 or later will likely work */
00408       exit(1);
00409    }
00410     
00411    /* Confirm that the WinSock DLL supports 2.2.*/
00412    /* Note that if the DLL supports versions greater    */
00413    /* than 2.2 in addition to 2.2, it will still return */
00414    /* 2.2 in wVersion since that is the version we      */
00415    /* requested.                                        */
00416     
00417    if ( LOBYTE( wsaData.wVersion ) != 2 ||
00418         HIBYTE( wsaData.wVersion ) != 2 ) 
00419    {
00420       /* Tell the user that we could not find a usable */
00421       /* WinSock DLL.                                  */
00422       WSACleanup( );
00423       printf("Bad winsock verion\n");
00424       assert(0); /* is this is failing, try a different version that 2.2, 1.0 or later will likely work */
00425       exit(1);
00426    }    
00427 #endif
00428 }
00429 
00430 
00431 /* ====================================================================
00432  * The Vovida Software License, Version 1.0 
00433  * 
00434  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00435  * 
00436  * Redistribution and use in source and binary forms, with or without
00437  * modification, are permitted provided that the following conditions
00438  * are met:
00439  * 
00440  * 1. Redistributions of source code must retain the above copyright
00441  *    notice, this list of conditions and the following disclaimer.
00442  * 
00443  * 2. Redistributions in binary form must reproduce the above copyright
00444  *    notice, this list of conditions and the following disclaimer in
00445  *    the documentation and/or other materials provided with the
00446  *    distribution.
00447  * 
00448  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00449  *    and "Vovida Open Communication Application Library (VOCAL)" must
00450  *    not be used to endorse or promote products derived from this
00451  *    software without prior written permission. For written
00452  *    permission, please contact vocal@vovida.org.
00453  *
00454  * 4. Products derived from this software may not be called "VOCAL", nor
00455  *    may "VOCAL" appear in their name, without prior written
00456  *    permission of Vovida Networks, Inc.
00457  * 
00458  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00459  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00460  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00461  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00462  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00463  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00464  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00465  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00466  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00467  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00468  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00469  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00470  * DAMAGE.
00471  * 
00472  * ====================================================================
00473  * 
00474  * This software consists of voluntary contributions made by Vovida
00475  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00476  * Inc.  For more information on Vovida Networks, Inc., please see
00477  * <http://www.vovida.org/>.
00478  *
00479  */
00480 
00481 /* Local Variables:
00482    mode:c
00483    c-file-style:"ellemtel"
00484    c-file-offsets:((case-label . +))
00485    indent-tabs-mode:nil
00486    End:
00487 */

Generated on Wed Aug 29 01:39:22 2007 for oRTP by  doxygen 1.5.2