pipstm.cxx (4410B)
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 // internet (ipv4) socket 34 // 35 36 37 ipstream::ipstream() 38 : fdxstm(), ippeerinfo(0, nullstring, 0), svsocket(invhandle) {} 39 40 41 ipstream::ipstream(ipaddress iip, int iport) 42 : fdxstm(), ippeerinfo(iip, nullstring, iport), svsocket(invhandle) {} 43 44 45 ipstream::ipstream(const char* ihost, int iport) 46 : fdxstm(), ippeerinfo(ipnone, ihost, iport), svsocket(invhandle) {} 47 48 49 ipstream::ipstream(const string& ihost, int iport) 50 : fdxstm(), ippeerinfo(ipnone, ihost, iport), svsocket(invhandle) {} 51 52 53 ipstream::~ipstream() 54 { 55 cancel(); 56 } 57 58 59 int ipstream::classid() 60 { 61 return CLASS3_IPSTM; 62 } 63 64 65 int ipstream::uerrno() 66 { 67 return usockerrno(); 68 } 69 70 71 const char* ipstream::uerrmsg(int code) 72 { 73 return usockerrmsg(code); 74 } 75 76 77 string ipstream::get_streamname() 78 { 79 return ippeerinfo::asstring(true); 80 } 81 82 83 void ipstream::set_ip(ipaddress iip) 84 { 85 close(); 86 ip = iip; 87 ptypes::clear(host); 88 } 89 90 91 void ipstream::set_host(const string& ihost) 92 { 93 close(); 94 host = ihost; 95 ip = ipnone; 96 } 97 98 99 void ipstream::set_host(const char* ihost) 100 { 101 close(); 102 host = ihost; 103 ip = ipnone; 104 } 105 106 107 void ipstream::set_port(int iport) 108 { 109 close(); 110 port = iport; 111 } 112 113 114 void ipstream::doopen() 115 { 116 sockaddr_in sa; 117 memset(&sa, 0, sizeof(sa)); 118 119 if (svsocket != invhandle) 120 { 121 psocklen addrlen = sizeof(sa); 122 123 // open an active server socket and assign ip and host fields 124 chstat(IO_CONNECTING); 125 126 // the last parameter of accept() can be either int* or uint* 127 // depending on the target platform :( 128 if ((handle = ::accept(svsocket, (sockaddr*)&sa, &addrlen)) < 0) 129 error(uerrno(), "Couldn't create socket"); 130 chstat(IO_CONNECTED); 131 132 if (sa.sin_family != AF_INET) 133 error(EAFNOSUPPORT, "Address family not supported"); 134 135 ptypes::clear(host); 136 ip = sa.sin_addr.s_addr; 137 port = ntohs(sa.sin_port); 138 } 139 140 else 141 { 142 sa.sin_family = AF_INET; 143 sa.sin_port = htons(ushort(get_port())); 144 145 chstat(IO_RESOLVING); 146 sa.sin_addr.s_addr = get_ip(); // force to resolve the address if needed 147 chstat(IO_RESOLVED); 148 149 // open a client socket 150 if ((handle = ::socket(sa.sin_family, SOCK_STREAM, 0)) < 0) 151 error(uerrno(), "Couldn't create socket"); 152 153 // a chance to set up extra socket options 154 sockopt(handle); 155 156 chstat(IO_CONNECTING); 157 if (::connect(handle, (sockaddr*)&sa, sizeof(sa)) < 0) 158 { 159 int e = uerrno(); 160 closehandle(); 161 error(e, "Couldn't connect to remote host"); 162 } 163 chstat(IO_CONNECTED); 164 } 165 } 166 167 168 void ipstream::sockopt(int) 169 { 170 } 171 172 173 void ipstream::closehandle() 174 { 175 ::closesocket(pexchange(&handle, invhandle)); 176 } 177 178 179 large ipstream::doseek(large, ioseekmode) 180 { 181 return -1; 182 } 183 184 185 void ipstream::doclose() 186 { 187 svsocket = invhandle; 188 if (!cancelled) 189 ::shutdown(handle, SHUT_RDWR); 190 closehandle(); 191 } 192 193 194 #ifdef WIN32 195 196 int ipstream::dorawread(char* buf, int count) 197 { 198 int ret; 199 if ((ret = ::recv(handle, buf, count, 0)) == -1) 200 error(uerrno(), "Couldn't read"); 201 return ret; 202 } 203 204 205 int ipstream::dorawwrite(const char* buf, int count) 206 { 207 int ret; 208 if ((ret = ::send(handle, buf, count, 0)) == -1) 209 error(uerrno(), "Couldn't write"); 210 return ret; 211 } 212 213 #endif 214 215 216 bool ipstream::waitfor(int timeout) 217 { 218 if (!active) 219 errstminactive(); 220 if (bufsize > 0 && bufend > bufpos) 221 return true; 222 return psockwait(handle, timeout); 223 } 224 225 226 ipaddress ipstream::get_myip() 227 { 228 if (!active) 229 errstminactive(); 230 ippeerinfo p; 231 if (!psockname(handle, p)) 232 error(uerrno(), "Couldn't get my IP"); 233 return p.get_ip(); 234 } 235 236 237 int ipstream::get_myport() 238 { 239 if (!active) 240 errstminactive(); 241 ippeerinfo p; 242 if (!psockname(handle, p)) 243 error(uerrno(), "Couldn't get my port number"); 244 return p.get_port(); 245 } 246 247 248 }