00001
00002
00003
00004
00005
00006
00007
00008 #include "wvudp.h"
00009
00010 #ifndef WIN32
00011 #include <sys/socket.h>
00012 #else
00013 #define setsockopt(a,b,c,d,e) setsockopt(a,b,c, (const char*) d,e)
00014 #define recvfrom(a,b,c,d,e,f) recvfrom(a, (char *) b, c, d, e, f)
00015 #define sendto(a,b,c,d,e,f) sendto(a,(const char*) b,c,d,e,f)
00016 #undef errno
00017 #define errno GetLastError()
00018 #endif
00019
00020 #include <fcntl.h>
00021
00022 #ifdef ISDARWIN
00023 # define socklen_t int
00024 #endif
00025
00026 WvUDPStream::WvUDPStream(const WvIPPortAddr &_local,
00027 const WvIPPortAddr &_rem) :
00028 localaddr(), remaddr(_rem)
00029 {
00030 int x = 1;
00031 setfd(socket(PF_INET, SOCK_DGRAM, 0));
00032 if (getfd() < 0
00033 || setsockopt(getfd(), SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0)
00034 {
00035 seterr(errno);
00036 return;
00037 }
00038
00039 set_close_on_exec(true);
00040 set_nonblock(true);
00041
00042 struct sockaddr *sa = _local.sockaddr();
00043 if (bind(getfd(), sa, _local.sockaddr_len()))
00044 {
00045 delete sa;
00046 seterr(errno);
00047 return;
00048 }
00049 delete sa;
00050
00051 struct sockaddr_in nsa;
00052 socklen_t nsalen = sizeof(nsa);
00053 if (getsockname(getfd(), (sockaddr *)&nsa, &nsalen) < 0)
00054 {
00055 seterr(errno);
00056 return;
00057 }
00058 localaddr = WvIPPortAddr(&nsa);
00059
00060 if (WvIPAddr(_rem) != WvIPAddr())
00061 {
00062 struct sockaddr *sa = _rem.sockaddr();
00063 if (connect(getfd(), sa, _rem.sockaddr_len()))
00064 {
00065 delete sa;
00066 seterr(errno);
00067 return;
00068 }
00069 delete sa;
00070 }
00071 }
00072
00073
00074 WvUDPStream::~WvUDPStream()
00075 {
00076 }
00077
00078
00079 const WvAddr *WvUDPStream::src() const
00080 {
00081 return &remaddr;
00082 }
00083
00084
00085 const WvAddr *WvUDPStream::local() const
00086 {
00087 return &localaddr;
00088 }
00089
00090
00091 size_t WvUDPStream::uread(void *buf, size_t count)
00092 {
00093 if (!isok() || !buf || !count) return 0;
00094
00095 struct sockaddr_in from;
00096 socklen_t fromlen = sizeof(from);
00097 int in = recvfrom(getfd(), buf, count, 0, (sockaddr *)&from, &fromlen);
00098
00099 if (in >= 0)
00100 remaddr = WvIPPortAddr(&from);
00101
00102
00103 return in < 0 ? 0 : in;
00104 }
00105
00106
00107 size_t WvUDPStream::uwrite(const void *buf, size_t count)
00108 {
00109 if (!isok() || !buf || !count) return 0;
00110
00111
00112 if (remaddr.is_zero()) return count;
00113
00114 struct sockaddr *to = remaddr.sockaddr();
00115 size_t tolen = remaddr.sockaddr_len();
00116 int out;
00117
00118 out = sendto(getfd(), buf, count, 0, to, tolen);
00119
00120 if (out < 0 && errno == EACCES)
00121 seterr(EACCES);
00122
00123 delete to;
00124
00125
00126
00127
00128
00129 return out < 0 ? 0 : out;
00130 }
00131
00132
00133 void WvUDPStream::enable_broadcasts()
00134 {
00135 int value = 1;
00136
00137 if (!isok()) return;
00138
00139 setsockopt(getfd(), SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
00140 }