WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvIPRawStream can send and receive packets on a connectionless IP socket. 00006 * See wvipraw.h for details. 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 // errors in IP are ignored 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) // permission denied 00109 seterr(EACCES); 00110 00111 free(to); 00112 00113 // errors in UDP are ignored 00114 // pretend that the write always succeeds even if the kernel 00115 // complains since we don't want datagrams backing up in the 00116 // buffer and forming merged datagrams as a result 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 }