00001
00002
00003
00004
00005
00006
00007
00008 #include "wvudp.h"
00009 #include <sys/socket.h>
00010 #include <fcntl.h>
00011
00012
00013 WvUDPStream::WvUDPStream(const WvIPPortAddr &_local, const WvIPPortAddr &_rem)
00014 : localaddr(), remaddr(_rem)
00015 {
00016 rwfd = socket(PF_INET, SOCK_DGRAM, 0);
00017 if (getfd() < 0
00018 || fcntl(getfd(), F_SETFD, 1)
00019 || fcntl(getfd(), F_SETFL, O_RDWR | O_NONBLOCK)
00020 )
00021 {
00022 seterr(errno);
00023 return;
00024 }
00025
00026 struct sockaddr *sa = _local.sockaddr();
00027 if (bind(getfd(), sa, _local.sockaddr_len()))
00028 {
00029 delete sa;
00030 seterr(errno);
00031 return;
00032 }
00033 delete sa;
00034
00035 struct sockaddr_in nsa;
00036 socklen_t nsalen = sizeof(nsa);
00037 if (getsockname(getfd(), (sockaddr *)&nsa, &nsalen) < 0)
00038 {
00039 seterr(errno);
00040 return;
00041 }
00042 localaddr = WvIPPortAddr(&nsa);
00043
00044 if (WvIPAddr(_rem) != WvIPAddr())
00045 {
00046 struct sockaddr *sa = _rem.sockaddr();
00047 if (connect(getfd(), sa, _rem.sockaddr_len()))
00048 {
00049 delete sa;
00050 seterr(errno);
00051 return;
00052 }
00053 delete sa;
00054 }
00055 }
00056
00057
00058 WvUDPStream::~WvUDPStream()
00059 {
00060 }
00061
00062
00063 const WvAddr *WvUDPStream::src() const
00064 {
00065 return &remaddr;
00066 }
00067
00068
00069 const WvAddr *WvUDPStream::local() const
00070 {
00071 return &localaddr;
00072 }
00073
00074
00075 size_t WvUDPStream::uread(void *buf, size_t count)
00076 {
00077 if (!isok() || !buf || !count) return 0;
00078
00079 struct sockaddr_in from;
00080 socklen_t fromlen = sizeof(from);
00081 int in = recvfrom(getfd(), buf, count, 0, (sockaddr *)&from, &fromlen);
00082
00083 if (in >= 0)
00084 remaddr = WvIPPortAddr(&from);
00085
00086
00087 return in < 0 ? 0 : in;
00088 }
00089
00090
00091 size_t WvUDPStream::uwrite(const void *buf, size_t count)
00092 {
00093 if (!isok() || !buf || !count) return 0;
00094
00095 struct sockaddr *to = remaddr.sockaddr();
00096 size_t tolen = remaddr.sockaddr_len();
00097 int out;
00098
00099 out = sendto(getfd(), buf, count, 0, to, tolen);
00100
00101 if (out < 0 && errno == EACCES)
00102 seterr(EACCES);
00103
00104 free(to);
00105
00106
00107 return out < 0 ? 0 : out;
00108 }
00109
00110
00111 void WvUDPStream::enable_broadcasts()
00112 {
00113 int value = 1;
00114
00115 if (!isok()) return;
00116
00117 setsockopt(getfd(), SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
00118 }