WvStreams
wvudp.cc
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"
9 
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
19 
20 #include <fcntl.h>
21 
22 #ifdef ISDARWIN
23 # define socklen_t int
24 #endif
25 
27  const WvIPPortAddr &_rem) :
28  localaddr(), remaddr(_rem)
29 {
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)
34  {
35  seterr(errno);
36  return;
37  }
38 
39  set_close_on_exec(true);
40  set_nonblock(true);
41 
42  struct sockaddr *sa = _local.sockaddr();
43  if (bind(getfd(), sa, _local.sockaddr_len()))
44  {
45  delete sa;
46  seterr(errno);
47  return;
48  }
49  delete sa;
50 
51  struct sockaddr_in nsa;
52  socklen_t nsalen = sizeof(nsa);
53  if (getsockname(getfd(), (sockaddr *)&nsa, &nsalen) < 0)
54  {
55  seterr(errno);
56  return;
57  }
58  localaddr = WvIPPortAddr(&nsa);
59 
60  if (WvIPAddr(_rem) != WvIPAddr())
61  {
62  struct sockaddr *sa = _rem.sockaddr();
63  if (connect(getfd(), sa, _rem.sockaddr_len()))
64  {
65  delete sa;
66  seterr(errno);
67  return;
68  }
69  delete sa;
70  }
71 }
72 
73 
74 WvUDPStream::~WvUDPStream()
75 {
76 }
77 
78 
79 const WvAddr *WvUDPStream::src() const
80 {
81  return &remaddr;
82 }
83 
84 
85 const WvAddr *WvUDPStream::local() const
86 {
87  return &localaddr;
88 }
89 
90 
91 size_t WvUDPStream::uread(void *buf, size_t count)
92 {
93  if (!isok() || !buf || !count) return 0;
94 
95  struct sockaddr_in from;
96  socklen_t fromlen = sizeof(from);
97  int in = recvfrom(getfd(), buf, count, 0, (sockaddr *)&from, &fromlen);
98 
99  if (in >= 0)
100  remaddr = WvIPPortAddr(&from);
101 
102  // errors in UDP are ignored
103  return in < 0 ? 0 : in;
104 }
105 
106 
107 size_t WvUDPStream::uwrite(const void *buf, size_t count)
108 {
109  if (!isok() || !buf || !count) return 0;
110 
111  // pretend everything worked if there is nowhere to send data
112  if (remaddr.is_zero()) return count;
113 
114  struct sockaddr *to = remaddr.sockaddr();
115  size_t tolen = remaddr.sockaddr_len();
116  int out;
117 
118  out = sendto(getfd(), buf, count, 0, to, tolen);
119 
120  if (out < 0 && errno == EACCES) // permission denied
121  seterr(EACCES);
122 
123  delete to;
124 
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;
130 }
131 
132 
133 void WvUDPStream::enable_broadcasts()
134 {
135  int value = 1;
136 
137  if (!isok()) return;
138 
139  setsockopt(getfd(), SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
140 }
WvFdStream::isok
virtual bool isok() const
return true if the stream is actually usable right now
Definition: wvfdstream.cc:134
WvUDPStream::src
virtual const WvAddr * src() const
return the remote address (source of incoming packets, target of outgoing packets).
Definition: wvudp.cc:79
WvStream::seterr
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
Definition: wvstream.cc:451
WvUDPStream::uread
virtual size_t uread(void *buf, size_t count)
unbuffered I/O functions; these ignore the buffer, which is handled by read().
Definition: wvudp.cc:91
WvFdStream::setfd
void setfd(int fd)
Sets the file descriptor for both reading and writing.
Definition: wvfdstream.h:36
WvUDPStream::uwrite
virtual size_t uwrite(const void *buf, size_t count)
unbuffered I/O functions; these ignore the buffer, which is handled by write().
Definition: wvudp.cc:107
WvIPPortAddr
An IP+Port address also includes a port number, with the resulting form www.xxx.yyy....
Definition: wvaddr.h:393
WvAddr
Base class for different address types, each of which will have the ability to convert itself to/from...
Definition: wvaddr.h:118
WvFdStream::getfd
int getfd() const
Returns the Unix file descriptor for reading and writing.
Definition: wvfdstream.h:81
WvFdStream::set_close_on_exec
void set_close_on_exec(bool close_on_exec)
Make the fds on this stream close-on-exec or not.
Definition: wvfdstream.cc:107
WvIPAddr
An IP address is made up of a "dotted quad" – four decimal numbers in the form www....
Definition: wvaddr.h:249
WvFdStream::set_nonblock
void set_nonblock(bool nonblock)
Make the fds on this stream blocking or non-blocking.
Definition: wvfdstream.cc:97
WvUDPStream::WvUDPStream
WvUDPStream(const WvIPPortAddr &_local, const WvIPPortAddr &_rem)
connect a new socket
Definition: wvudp.cc:26