Make WvStreams compile with gcc 4.4.
[wvstreams.git] / ipstreams / wvudp.cc
blob631b3d59076516efe4c6315875103de1db873565
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * WvUDPStream can send and receive packets on a connectionless UDP socket.
6 * See wvudp.h for details.
7 */
8 #include "wvudp.h"
10 #ifndef WIN32
11 #include <sys/socket.h>
12 #else
13 #define setsockopt(a,b,c,d,e) setsockopt(a,b,c, (const char*) d,e)
14 #define recvfrom(a,b,c,d,e,f) recvfrom(a, (char *) b, c, d, e, f)
15 #define sendto(a,b,c,d,e,f) sendto(a,(const char*) b,c,d,e,f)
16 #undef errno
17 #define errno GetLastError()
18 #endif
20 #include <fcntl.h>
22 #ifdef ISDARWIN
23 # define socklen_t int
24 #endif
26 WvUDPStream::WvUDPStream(const WvIPPortAddr &_local,
27 const WvIPPortAddr &_rem) :
28 localaddr(), remaddr(_rem)
30 int x = 1;
31 setfd(socket(PF_INET, SOCK_DGRAM, 0));
32 if (getfd() < 0
33 || setsockopt(getfd(), SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0)
35 seterr(errno);
36 return;
39 set_close_on_exec(true);
40 set_nonblock(true);
42 struct sockaddr *sa = _local.sockaddr();
43 if (bind(getfd(), sa, _local.sockaddr_len()))
45 delete sa;
46 seterr(errno);
47 return;
49 delete sa;
51 struct sockaddr_in nsa;
52 socklen_t nsalen = sizeof(nsa);
53 if (getsockname(getfd(), (sockaddr *)&nsa, &nsalen) < 0)
55 seterr(errno);
56 return;
58 localaddr = WvIPPortAddr(&nsa);
60 if (WvIPAddr(_rem) != WvIPAddr())
62 struct sockaddr *sa = _rem.sockaddr();
63 if (connect(getfd(), sa, _rem.sockaddr_len()))
65 delete sa;
66 seterr(errno);
67 return;
69 delete sa;
74 WvUDPStream::~WvUDPStream()
79 const WvAddr *WvUDPStream::src() const
81 return &remaddr;
85 const WvAddr *WvUDPStream::local() const
87 return &localaddr;
91 size_t WvUDPStream::uread(void *buf, size_t count)
93 if (!isok() || !buf || !count) return 0;
95 struct sockaddr_in from;
96 socklen_t fromlen = sizeof(from);
97 int in = recvfrom(getfd(), buf, count, 0, (sockaddr *)&from, &fromlen);
99 if (in >= 0)
100 remaddr = WvIPPortAddr(&from);
102 // errors in UDP are ignored
103 return in < 0 ? 0 : in;
107 size_t WvUDPStream::uwrite(const void *buf, size_t count)
109 if (!isok() || !buf || !count) return 0;
111 // pretend everything worked if there is nowhere to send data
112 if (remaddr.is_zero()) return count;
114 struct sockaddr *to = remaddr.sockaddr();
115 size_t tolen = remaddr.sockaddr_len();
116 int out;
118 out = sendto(getfd(), buf, count, 0, to, tolen);
120 if (out < 0 && errno == EACCES) // permission denied
121 seterr(EACCES);
123 delete to;
125 // errors in UDP are ignored
126 // pretend that the write always succeeds even if the kernel
127 // complains since we don't want datagrams backing up in the
128 // buffer and forming merged datagrams as a result
129 return out < 0 ? 0 : out;
133 void WvUDPStream::enable_broadcasts()
135 int value = 1;
137 if (!isok()) return;
139 setsockopt(getfd(), SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));