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 || setsockopt(getfd(), SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0)
00025 {
00026 seterr(errno);
00027 return;
00028 }
00029
00030 set_close_on_exec(true);
00031 set_nonblock(true);
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 }