reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
Udp.cxx
Go to the documentation of this file.
1#include "rutil/ResipAssert.h"
2#include <cstdio>
3#include <cstring>
4#include <errno.h>
5#include <iostream>
6#include <cstdlib>
7#include <time.h>
8
9#ifdef WIN32
10
11#include <winsock2.h>
12#include <stdlib.h>
13#include <io.h>
14
15#else
16
17#include <arpa/inet.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <fcntl.h>
21#include <netinet/in.h>
22#include <sys/socket.h>
23#include <sys/types.h>
24#include <netdb.h>
25#include <string.h>
26#include <unistd.h>
27
28#endif
29
30#include <string.h>
31
32#include "rutil/stun/Udp.hxx"
33
34using namespace std;
35using namespace resip;
36
38openPort( unsigned short port, unsigned int interfaceIp, bool verbose )
39{
41
42 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
43 if ( fd == INVALID_SOCKET )
44 {
45 int err = getErrno();
46 cerr << "Could not create a UDP socket:" << err << endl;
47 return INVALID_SOCKET;
48 }
49
50 struct sockaddr_in addr;
51 memset((char*) &(addr),0, sizeof((addr)));
52 addr.sin_family = AF_INET;
53 addr.sin_addr.s_addr = htonl(INADDR_ANY);
54 addr.sin_port = htons(port);
55
56 if ( (interfaceIp != 0) &&
57 ( interfaceIp != 0x100007f ) )
58 {
59 addr.sin_addr.s_addr = htonl(interfaceIp);
60 if (verbose )
61 {
62 clog << "Binding to interface "
63 << hex << "0x" << htonl(interfaceIp) << dec << endl;
64 }
65 }
66
67 if ( ::bind( fd,(struct sockaddr*)&addr, sizeof(addr)) != 0 )
68 {
69 int e = getErrno();
70
71 switch (e)
72 {
73 case 0:
74 {
75 cerr << "Could not bind socket" << endl;
76 closeSocket(fd);
77 return INVALID_SOCKET;
78 }
79 case EADDRINUSE:
80 {
81 cerr << "Port " << port << " for receiving UDP is in use" << endl;
82 closeSocket(fd);
83 return INVALID_SOCKET;
84 }
85 break;
86 case EADDRNOTAVAIL:
87 {
88 if ( verbose )
89 {
90 cerr << "Cannot assign requested address" << endl;
91 }
92 closeSocket(fd);
93 return INVALID_SOCKET;
94 }
95 break;
96 default:
97 {
98 cerr << "Could not bind UDP receive port"
99 << "Error=" << e << " " << strError(e) << endl;
100 closeSocket(fd);
101 return INVALID_SOCKET;
102 }
103 break;
104 }
105 }
106 if ( verbose )
107 {
108 clog << "Opened port " << port << " with fd " << fd << endl;
109 }
110
112
113 return fd;
114}
115
116
117bool
118getMessage( resip::Socket fd, char* buf, int* len,
119 uint32_t* srcIp, unsigned short* srcPort,
120 bool verbose)
121{
123
124 int originalSize = *len;
125 resip_assert( originalSize > 0 );
126
127 struct sockaddr_in from;
128 int fromLen = sizeof(from);
129
130 *len = recvfrom(fd,
131 buf,
132 originalSize,
133 0,
134 (struct sockaddr *)&from,
135 (socklen_t*)&fromLen);
136
137 if ( *len == SOCKET_ERROR )
138 {
139 int err = getErrno();
140
141 switch (err)
142 {
143 case ENOTSOCK:
144 cerr << "Error fd not a socket" << endl;
145 break;
146 case ECONNRESET:
147 cerr << "Error connection reset - host not reachable" << endl;
148 break;
149
150 default:
151 cerr << "Socket Error=" << err << endl;
152 }
153
154 return false;
155 }
156
157 if ( *len < 0 )
158 {
159 clog << "socket closed? negative len" << endl;
160 return false;
161 }
162
163 if ( *len == 0 )
164 {
165 clog << "socket closed? zero len" << endl;
166 return false;
167 }
168
169 *srcPort = ntohs(from.sin_port);
170 *srcIp = ntohl(from.sin_addr.s_addr);
171
172 if ( (*len)+1 >= originalSize )
173 {
174 if (verbose)
175 {
176 clog << "Received a message that was too large" << endl;
177 }
178 return false;
179 }
180 buf[*len]=0;
181
182 return true;
183}
184
185
186bool
187sendMessage( resip::Socket fd, char* buf, int l,
188 unsigned int dstIp, unsigned short dstPort,
189 bool verbose)
190{
192
193 int s;
194 if ( dstPort == 0 )
195 {
196 // sending on a connected port
197 resip_assert( dstIp == 0 );
198
199 s = send(fd,buf,l,0);
200 }
201 else
202 {
203 resip_assert( dstIp != 0 );
204 resip_assert( dstPort != 0 );
205
206 struct sockaddr_in to;
207 int toLen = sizeof(to);
208 memset(&to,0,toLen);
209
210 to.sin_family = AF_INET;
211 to.sin_port = htons(dstPort);
212 to.sin_addr.s_addr = htonl(dstIp);
213
214 s = sendto(fd, buf, l, 0,(sockaddr*)&to, toLen);
215 }
216
217 if ( s == SOCKET_ERROR )
218 {
219 int e = getErrno();
220 switch (e)
221 {
222 case ECONNREFUSED:
223 case EHOSTDOWN:
224 case EHOSTUNREACH:
225 {
226 // quietly ignore this
227 }
228 break;
229 case EAFNOSUPPORT:
230 {
231 cerr << "err EAFNOSUPPORT in send" << endl;
232 }
233 break;
234 default:
235 {
236 cerr << "err " << e << " " << strError(e) << " in send" << endl;
237 }
238 }
239 return false;
240 }
241
242 if ( s == 0 )
243 {
244 cerr << "no data sent in send" << endl;
245 return false;
246 }
247
248 if ( s != l )
249 {
250 if (verbose)
251 {
252 cerr << "only " << s << " out of " << l << " bytes sent" << endl;
253 }
254 return false;
255 }
256
257 return true;
258}
259
260/* ====================================================================
261 * The Vovida Software License, Version 1.0
262 *
263 * Redistribution and use in source and binary forms, with or without
264 * modification, are permitted provided that the following conditions
265 * are met:
266 *
267 * 1. Redistributions of source code must retain the above copyright
268 * notice, this list of conditions and the following disclaimer.
269 *
270 * 2. Redistributions in binary form must reproduce the above copyright
271 * notice, this list of conditions and the following disclaimer in
272 * the documentation and/or other materials provided with the
273 * distribution.
274 *
275 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
276 * and "Vovida Open Communication Application Library (VOCAL)" must
277 * not be used to endorse or promote products derived from this
278 * software without prior written permission. For written
279 * permission, please contact vocal@vovida.org.
280 *
281 * 4. Products derived from this software may not be called "VOCAL", nor
282 * may "VOCAL" appear in their name, without prior written
283 * permission of Vovida Networks, Inc.
284 *
285 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
286 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
287 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
288 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
289 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
290 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
291 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
292 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
293 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
294 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
295 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
296 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
297 * DAMAGE.
298 *
299 */
300
301// Local Variables:
302// mode:c++
303// c-file-style:"ellemtel"
304// c-file-offsets:((case-label . +))
305// indent-tabs-mode:nil
306// End:
#define resip_assert(x)
This file needs to work for both C and C++ code.
#define INVALID_SOCKET
Definition Socket.hxx:95
#define SOCKET_ERROR
Definition Socket.hxx:96
resip::Socket openPort(unsigned short port, unsigned int interfaceIp, bool verbose)
Open a UDP socket to receive on the given port - if port is 0, pick a a port, if interfaceIp!...
Definition Udp.cxx:38
bool getMessage(resip::Socket fd, char *buf, int *len, uint32_t *srcIp, unsigned short *srcPort, bool verbose)
recive a UDP message
Definition Udp.cxx:118
bool sendMessage(resip::Socket fd, char *buf, int l, unsigned int dstIp, unsigned short dstPort, bool verbose)
send a UDP message
Definition Udp.cxx:187
dcm! – add UnusedChecking(_enum) below;
int Socket
Definition Socket.hxx:94
int closeSocket(Socket fd)
Definition Socket.cxx:134
int getErrno()
Definition Socket.hxx:97
std::string strError(int err)
Definition compat.hxx:274
unsigned int uint32_t
Definition stdint.h:85