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 #ifndef _WIN32
00034 || fcntl(getfd(), F_SETFD, 1)
00035 || fcntl(getfd(), F_SETFL, O_RDWR | O_NONBLOCK)
00036 #else
00037 || ioctlsocket(getfd(), FIONBIO, (u_long*) &x)
00038 #endif
00039 || setsockopt(getfd(), SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0
00040 )
00041 {
00042 seterr(errno);
00043 return;
00044 }
00045
00046 struct sockaddr *sa = _local.sockaddr();
00047 if (bind(getfd(), sa, _local.sockaddr_len()))
00048 {
00049 delete sa;
00050 seterr(errno);
00051 return;
00052 }
00053 delete sa;
00054
00055 struct sockaddr_in nsa;
00056 socklen_t nsalen = sizeof(nsa);
00057 if (getsockname(getfd(), (sockaddr *)&nsa, &nsalen) < 0)
00058 {
00059 seterr(errno);
00060 return;
00061 }
00062 localaddr = WvIPPortAddr(&nsa);
00063
00064 if (WvIPAddr(_rem) != WvIPAddr())
00065 {
00066 struct sockaddr *sa = _rem.sockaddr();
00067 if (connect(getfd(), sa, _rem.sockaddr_len()))
00068 {
00069 delete sa;
00070 seterr(errno);
00071 return;
00072 }
00073 delete sa;
00074 }
00075 }
00076
00077
00078 WvUDPStream::~WvUDPStream()
00079 {
00080 }
00081
00082
00083 const WvAddr *WvUDPStream::src() const
00084 {
00085 return &remaddr;
00086 }
00087
00088
00089 const WvAddr *WvUDPStream::local() const
00090 {
00091 return &localaddr;
00092 }
00093
00094
00095 size_t WvUDPStream::uread(void *buf, size_t count)
00096 {
00097 if (!isok() || !buf || !count) return 0;
00098
00099 struct sockaddr_in from;
00100 socklen_t fromlen = sizeof(from);
00101 int in = recvfrom(getfd(), buf, count, 0, (sockaddr *)&from, &fromlen);
00102
00103 if (in >= 0)
00104 remaddr = WvIPPortAddr(&from);
00105
00106
00107 return in < 0 ? 0 : in;
00108 }
00109
00110
00111 size_t WvUDPStream::uwrite(const void *buf, size_t count)
00112 {
00113 if (!isok() || !buf || !count) return 0;
00114
00115 struct sockaddr *to = remaddr.sockaddr();
00116 size_t tolen = remaddr.sockaddr_len();
00117 int out;
00118
00119 out = sendto(getfd(), buf, count, 0, to, tolen);
00120
00121 if (out < 0 && errno == EACCES)
00122 seterr(EACCES);
00123
00124 free(to);
00125
00126
00127
00128
00129
00130 return out < 0 ? 0 : out;
00131 }
00132
00133
00134 void WvUDPStream::enable_broadcasts()
00135 {
00136 int value = 1;
00137
00138 if (!isok()) return;
00139
00140 setsockopt(getfd(), SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
00141 }