reSIProcate/rutil  9694
Udp.cxx
Go to the documentation of this file.
00001 #include <cassert>
00002 #include <cstdio>
00003 #include <cstring>
00004 #include <errno.h>
00005 #include <iostream>
00006 #include <cstdlib>
00007 #include <time.h>
00008 
00009 #ifdef WIN32
00010 
00011 #include <winsock2.h>
00012 #include <stdlib.h>
00013 #include <io.h>
00014 
00015 #else
00016 
00017 #include <arpa/inet.h>
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 #include <fcntl.h>
00021 #include <netinet/in.h>
00022 #include <sys/socket.h>
00023 #include <sys/types.h>
00024 #include <netdb.h>
00025 #include <string.h>
00026 #include <unistd.h>
00027 
00028 #endif
00029 
00030 #include <string.h>
00031 
00032 #include "rutil/stun/Udp.hxx"
00033 
00034 using namespace std;
00035 using namespace resip;
00036 
00037 resip::Socket
00038 openPort( unsigned short port, unsigned int interfaceIp, bool verbose )
00039 {
00040    resip::Socket fd;
00041     
00042    fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00043    if ( fd == INVALID_SOCKET )
00044    {
00045       int err = getErrno();
00046       cerr << "Could not create a UDP socket:" << err << endl;
00047       return INVALID_SOCKET;
00048    }
00049     
00050    struct sockaddr_in addr;
00051    memset((char*) &(addr),0, sizeof((addr)));
00052    addr.sin_family = AF_INET;
00053    addr.sin_addr.s_addr = htonl(INADDR_ANY);
00054    addr.sin_port = htons(port);
00055     
00056    if ( (interfaceIp != 0) && 
00057         ( interfaceIp != 0x100007f ) )
00058    {
00059       addr.sin_addr.s_addr = htonl(interfaceIp);
00060       if (verbose )
00061       {
00062          clog << "Binding to interface " 
00063               << hex << "0x" << htonl(interfaceIp) << dec << endl;
00064       }
00065    }
00066         
00067    if ( bind( fd,(struct sockaddr*)&addr, sizeof(addr)) != 0 )
00068    {
00069       int e = getErrno();
00070         
00071       switch (e)
00072       {
00073          case 0:
00074          {
00075             cerr << "Could not bind socket" << endl;
00076             closeSocket(fd);
00077             return INVALID_SOCKET;
00078          }
00079          case EADDRINUSE:
00080          {
00081             cerr << "Port " << port << " for receiving UDP is in use" << endl;
00082             closeSocket(fd);
00083             return INVALID_SOCKET;
00084          }
00085          break;
00086          case EADDRNOTAVAIL:
00087          {
00088             if ( verbose ) 
00089             {
00090                cerr << "Cannot assign requested address" << endl;
00091             }
00092             closeSocket(fd);
00093             return INVALID_SOCKET;
00094          }
00095          break;
00096          default:
00097          {
00098             cerr << "Could not bind UDP receive port"
00099                  << "Error=" << e << " " << strerror(e) << endl;
00100             closeSocket(fd);
00101             return INVALID_SOCKET;
00102          }
00103          break;
00104       }
00105    }
00106    if ( verbose )
00107    {
00108       clog << "Opened port " << port << " with fd " << fd << endl;
00109    }
00110    
00111    assert( fd != INVALID_SOCKET  );
00112         
00113    return fd;
00114 }
00115 
00116 
00117 bool 
00118 getMessage( resip::Socket fd, char* buf, int* len,
00119             UInt32* srcIp, unsigned short* srcPort,
00120             bool verbose)
00121 {
00122    assert( fd != INVALID_SOCKET );
00123         
00124    int originalSize = *len;
00125    assert( originalSize > 0 );
00126    
00127    struct sockaddr_in from;
00128    int fromLen = sizeof(from);
00129         
00130    *len = recvfrom(fd,
00131                    buf,
00132                    originalSize,
00133                    0,
00134                    (struct sockaddr *)&from,
00135                    (socklen_t*)&fromLen);
00136         
00137    if ( *len == SOCKET_ERROR )
00138    {
00139       int err = getErrno();
00140                 
00141       switch (err)
00142       {
00143          case ENOTSOCK:
00144             cerr << "Error fd not a socket" <<   endl;
00145             break;
00146          case ECONNRESET:
00147             cerr << "Error connection reset - host not reachable" <<   endl;
00148             break;
00149                                 
00150          default:
00151             cerr << "Socket Error=" << err << endl;
00152       }
00153                 
00154       return false;
00155    }
00156         
00157    if ( *len < 0 )
00158    {
00159       clog << "socket closed? negative len" << endl;
00160       return false;
00161    }
00162     
00163    if ( *len == 0 )
00164    {
00165       clog << "socket closed? zero len" << endl;
00166       return false;
00167    }
00168     
00169    *srcPort = ntohs(from.sin_port);
00170    *srcIp = ntohl(from.sin_addr.s_addr);
00171         
00172    if ( (*len)+1 >= originalSize )
00173    {
00174       if (verbose)
00175       {
00176          clog << "Received a message that was too large" << endl;
00177       }
00178       return false;
00179    }
00180    buf[*len]=0;
00181     
00182    return true;
00183 }
00184 
00185 
00186 bool 
00187 sendMessage( resip::Socket fd, char* buf, int l, 
00188              unsigned int dstIp, unsigned short dstPort,
00189              bool verbose)
00190 {
00191    assert( fd != INVALID_SOCKET );
00192     
00193    int s;
00194    if ( dstPort == 0 )
00195    {
00196       // sending on a connected port 
00197       assert( dstIp == 0 );
00198                 
00199       s = send(fd,buf,l,0);
00200    }
00201    else
00202    {
00203       assert( dstIp != 0 );
00204       assert( dstPort != 0 );
00205         
00206       struct sockaddr_in to;
00207       int toLen = sizeof(to);
00208       memset(&to,0,toLen);
00209         
00210       to.sin_family = AF_INET;
00211       to.sin_port = htons(dstPort);
00212       to.sin_addr.s_addr = htonl(dstIp);
00213         
00214       s = sendto(fd, buf, l, 0,(sockaddr*)&to, toLen);
00215    }
00216     
00217    if ( s == SOCKET_ERROR )
00218    {
00219       int e = getErrno();
00220       switch (e)
00221       {
00222          case ECONNREFUSED:
00223          case EHOSTDOWN:
00224          case EHOSTUNREACH:
00225          {
00226             // quietly ignore this 
00227          }
00228          break;
00229          case EAFNOSUPPORT:
00230          {
00231             cerr << "err EAFNOSUPPORT in send" << endl;
00232          }
00233          break;
00234          default:
00235          {
00236             cerr << "err " << e << " "  << strerror(e) << " in send" << endl;
00237          }
00238       }
00239       return false;
00240    }
00241     
00242    if ( s == 0 )
00243    {
00244       cerr << "no data sent in send" << endl;
00245       return false;
00246    }
00247     
00248    if ( s != l )
00249    {
00250       if (verbose)
00251       {
00252          cerr << "only " << s << " out of " << l << " bytes sent" << endl;
00253       }
00254       return false;
00255    }
00256     
00257    return true;
00258 }
00259 
00260 /* ====================================================================
00261  * The Vovida Software License, Version 1.0 
00262  * 
00263  * Redistribution and use in source and binary forms, with or without
00264  * modification, are permitted provided that the following conditions
00265  * are met:
00266  * 
00267  * 1. Redistributions of source code must retain the above copyright
00268  *    notice, this list of conditions and the following disclaimer.
00269  * 
00270  * 2. Redistributions in binary form must reproduce the above copyright
00271  *    notice, this list of conditions and the following disclaimer in
00272  *    the documentation and/or other materials provided with the
00273  *    distribution.
00274  * 
00275  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00276  *    and "Vovida Open Communication Application Library (VOCAL)" must
00277  *    not be used to endorse or promote products derived from this
00278  *    software without prior written permission. For written
00279  *    permission, please contact vocal@vovida.org.
00280  *
00281  * 4. Products derived from this software may not be called "VOCAL", nor
00282  *    may "VOCAL" appear in their name, without prior written
00283  *    permission of Vovida Networks, Inc.
00284  * 
00285  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00286  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00287  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00288  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00289  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00290  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00291  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00292  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00293  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00294  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00295  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00296  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00297  * DAMAGE.
00298  *
00299  */
00300 
00301 // Local Variables:
00302 // mode:c++
00303 // c-file-style:"ellemtel"
00304 // c-file-offsets:((case-label . +))
00305 // indent-tabs-mode:nil
00306 // End: