|
reSIProcate/rutil
9694
|
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:
1.7.5.1