pipmsg.cxx (3790B)
1 /* 2 * 3 * C++ Portable Types Library (PTypes) 4 * Version 2.1.1 Released 27-Jun-2007 5 * 6 * Copyright (C) 2001-2007 Hovik Melikyan 7 * 8 * http://www.melikyan.com/ptypes/ 9 * 10 */ 11 12 #ifdef WIN32 13 # include <winsock2.h> 14 #else 15 # include <sys/time.h> 16 # include <sys/types.h> 17 # include <sys/socket.h> 18 # include <netinet/in.h> 19 # include <arpa/inet.h> 20 # include <netdb.h> 21 # include <unistd.h> 22 # include <time.h> 23 #endif 24 25 26 #include "pinet.h" 27 28 29 namespace ptypes { 30 31 32 // 33 // ipmessage: IPv4 UDP message class 34 // 35 36 37 ipmessage::ipmessage() 38 : unknown(), ippeerinfo(ipnone, nullstring, 0), handle(invhandle) {} 39 40 41 ipmessage::ipmessage(ipaddress iip, int iport) 42 : unknown(), ippeerinfo(iip, nullstring, iport), handle(invhandle) {} 43 44 45 ipmessage::ipmessage(const char* ihost, int iport) 46 : unknown(), ippeerinfo(ipnone, ihost, iport), handle(invhandle) {} 47 48 49 ipmessage::ipmessage(const string& ihost, int iport) 50 : unknown(), ippeerinfo(ipnone, ihost, iport), handle(invhandle) {} 51 52 53 ipmessage::~ipmessage() 54 { 55 close(); 56 } 57 58 59 void ipmessage::set_ip(ipaddress iip) 60 { 61 ip = iip; 62 ptypes::clear(host); 63 } 64 65 66 void ipmessage::set_host(const string& ihost) 67 { 68 host = ihost; 69 ip = 0; 70 } 71 72 73 void ipmessage::set_host(const char* ihost) 74 { 75 host = ihost; 76 ip = 0; 77 } 78 79 80 void ipmessage::set_port(int iport) 81 { 82 port = iport; 83 } 84 85 86 ipaddress ipmessage::get_myip() 87 { 88 ippeerinfo p; 89 if (!psockname(handle, p)) 90 error(usockerrno(), "Couldn't get my IP"); 91 return p.get_ip(); 92 } 93 94 95 int ipmessage::get_myport() 96 { 97 ippeerinfo p; 98 if (!psockname(handle, p)) 99 error(usockerrno(), "Couldn't get my port number"); 100 return p.get_port(); 101 } 102 103 104 void ipmessage::close() 105 { 106 if (handle != invhandle) 107 ::closesocket(pexchange(&handle, invhandle)); 108 } 109 110 111 void ipmessage::open() 112 { 113 close(); 114 if ((handle = ::socket(AF_INET, SOCK_DGRAM, 0)) < 0) 115 error(usockerrno(), "Couldn't create socket"); 116 // allow broadcasts 117 int one = 1; 118 if (::setsockopt(handle, SOL_SOCKET, SO_BROADCAST, (sockval_t)&one, sizeof(one)) != 0) 119 error(usockerrno(), "Couldn't enable broadcasts"); 120 sockopt(handle); 121 } 122 123 124 void ipmessage::sockopt(int) 125 { 126 } 127 128 129 bool ipmessage::waitfor(int timeout) 130 { 131 return psockwait(handle, timeout); 132 } 133 134 135 void ipmessage::send(const char* buf, int count) 136 { 137 if (handle == invhandle) 138 open(); 139 140 sockaddr_in sa; 141 memset(&sa, 0, sizeof(sa)); 142 sa.sin_family = AF_INET; 143 sa.sin_port = htons(ushort(get_port())); 144 sa.sin_addr.s_addr = get_ip(); 145 if (sendto(handle, buf, count, 0, (sockaddr*)&sa, sizeof(sa)) < 0) 146 error(usockerrno(), "Couldn't write"); 147 } 148 149 150 int ipmessage::receive(char* buf, int count, ipaddress& src) 151 { 152 if (handle == invhandle) 153 error(EINVAL, "Couldn't read"); // must send() first 154 155 sockaddr_in sa; 156 psocklen fromlen = sizeof(sa); 157 int result = ::recvfrom(handle, buf, count, 0, (sockaddr*)&sa, &fromlen); 158 if (result < 0) 159 error(usockerrno(), "Couldn't read"); 160 src = sa.sin_addr.s_addr; 161 return result; 162 } 163 164 165 int ipmessage::receive(char* buf, int count) 166 { 167 ipaddress src; 168 return receive(buf, count, src); 169 } 170 171 172 string ipmessage::receive(int max, ipaddress& src) 173 { 174 string result; 175 setlength(result, max); 176 int numread = receive(pchar(pconst(result)), max, src); 177 setlength(result, numread); 178 return result; 179 } 180 181 182 string ipmessage::receive(int max) 183 { 184 ipaddress src; 185 return receive(max, src); 186 } 187 188 189 #ifdef _MSC_VER 190 // disable "unreachable code" warning for throw (known compiler bug) 191 # pragma warning (disable: 4702) 192 #endif 193 194 void ipmessage::error(int code, const char* msg) 195 { 196 string s = usockerrmsg(code); 197 if (isempty(s)) 198 s = msg; 199 throw new estream(nil, code, s + " [" + ippeerinfo::asstring(true) + ']'); 200 } 201 202 203 }