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 }