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