libsocket 1.5
|
00001 /* 00002 ** netsocket.cc 00003 ** Login : Julien Lemoine <speedblue@happycoder.org> 00004 ** Started on Mon May 12 22:23:27 2003 Julien Lemoine 00005 ** $Id: netsocket.cc,v 1.13 2004/11/24 21:25:36 speedblue Exp $ 00006 ** 00007 ** Copyright (C) 2003,2004 Julien Lemoine 00008 ** This program is free software; you can redistribute it and/or modify 00009 ** it under the terms of the GNU Lesser General Public License as published by 00010 ** the Free Software Foundation; either version 2 of the License, or 00011 ** (at your option) any later version. 00012 ** 00013 ** This program is distributed in the hope that it will be useful, 00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 ** GNU Lesser General Public License for more details. 00017 ** 00018 ** You should have received a copy of the GNU Lesser General Public License 00019 ** along with this program; if not, write to the Free Software 00020 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 */ 00022 00023 #include <iostream> 00024 #include "netsocket.hh" 00025 #include "socket.hxx" 00026 00027 namespace Network 00028 { 00029 00030 struct sockaddr_in NetSocket::_get_addr(const std::string& host, 00031 int port) const 00032 { 00033 struct hostent *he; 00034 struct sockaddr_in addr; 00035 00036 memset(&addr, 0, sizeof(struct sockaddr_in)); 00037 he = gethostbyname(host.c_str()); 00038 if (!he) 00039 throw HostnameError("Unknown Hostname", HERE); 00040 addr.sin_addr = *((struct in_addr *)he->h_addr); 00041 addr.sin_port = htons(port); 00042 addr.sin_family = AF_INET; 00043 return addr; 00044 } 00045 00046 #ifdef IPV6_ENABLED 00047 struct sockaddr_in6 NetSocket::_get_addr6(const std::string& host, 00048 int port) const 00049 { 00050 struct sockaddr_in6 addr; 00051 00052 memset(&addr, 0, sizeof(struct sockaddr_in6)); 00053 if ( inet_pton(AF_INET6, host.c_str(), &addr.sin6_addr) == 0 ) 00054 throw InetptonError("Unknown Hostname", HERE); 00055 addr.sin6_port = htons(port); 00056 addr.sin6_family = AF_INET6; 00057 return addr; 00058 } 00059 #endif 00060 00061 struct sockaddr_in NetSocket::_get_addr(int port) const 00062 { 00063 struct sockaddr_in addr; 00064 00065 memset(&addr, 0, sizeof(struct sockaddr_in)); 00066 addr.sin_addr.s_addr = htonl(INADDR_ANY); 00067 addr.sin_port = htons(port); 00068 addr.sin_family = AF_INET; 00069 return addr; 00070 } 00071 00072 #ifdef IPV6_ENABLED 00073 struct sockaddr_in6 NetSocket::_get_addr6(int port) const 00074 { 00075 struct sockaddr_in6 addr; 00076 00077 memset(&addr, 0, sizeof(struct sockaddr_in6)); 00078 if ( inet_pton(AF_INET6, "0::0", &addr.sin6_addr) == 0 ) 00079 throw InetptonError("Not a valid address", HERE); 00080 addr.sin6_port = htons(port); 00081 addr.sin6_family = AF_INET6; 00082 return addr; 00083 } 00084 #endif 00085 00086 int NetSocket::_bind(int port, const std::string& host) 00087 { 00088 int s; 00089 00090 if (_kind == UDP) 00091 { 00092 #ifdef IPV6_ENABLED 00093 if (_version == V4) 00094 #endif 00095 s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 00096 #ifdef IPV6_ENABLED 00097 else 00098 s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 00099 #endif 00100 } 00101 else if (_kind == TCP) 00102 { 00103 #ifdef IPV6_ENABLED 00104 if (_version == V4) 00105 #endif 00106 s = socket(PF_INET, SOCK_STREAM, 0); 00107 #ifdef IPV6_ENABLED 00108 else 00109 s = socket(PF_INET6, SOCK_STREAM, 0); 00110 #endif 00111 } 00112 else 00113 throw Exception("Unknown Protocole", HERE); 00114 00115 if (s < 0) 00116 throw SocketError("Socket error", HERE); 00117 #ifdef IPV6_ENABLED 00118 if (_version == V4) 00119 #endif 00120 _addr = _get_addr(host, port); 00121 #ifdef IPV6_ENABLED 00122 else 00123 _addr6 = _get_addr6(host, port); 00124 #endif 00125 return s; 00126 } 00127 00128 int NetSocket::_bind(int port) 00129 { 00130 int s, on; 00131 00132 if (_kind == TCP) 00133 { 00134 #ifdef IPV6_ENABLED 00135 if (_version == V4) 00136 #endif 00137 s = socket(PF_INET, SOCK_STREAM, 0); 00138 #ifdef IPV6_ENABLED 00139 else 00140 s = socket(PF_INET6, SOCK_STREAM, 0); 00141 #endif 00142 } 00143 else if (_kind == UDP) 00144 { 00145 #ifdef IPV6_ENABLED 00146 if (_version == V4) 00147 #endif 00148 s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 00149 #ifdef IPV6_ENABLED 00150 else 00151 s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 00152 #endif 00153 } 00154 else 00155 throw Exception("Unknown Protocole", HERE); 00156 if (s < 0) 00157 throw SocketError("Socket error", HERE); 00158 on = 1; 00159 00160 if (_kind == TCP && setsockopt(s, SOL_SOCKET, 00161 SO_REUSEADDR, (void *)&on, 00162 sizeof (on)) == -1) 00163 throw SetsockoptError("setsockopt error", HERE); 00164 00165 #ifdef IPV6_ENABLED 00166 if (_version == V4) 00167 { 00168 #endif 00169 struct sockaddr_in addr; 00170 addr = _get_addr(port); 00171 if (bind(s,(struct sockaddr*)&addr, (int)sizeof(addr)) == -1) 00172 throw BindError("Bind error", HERE); 00173 #ifdef IPV6_ENABLED 00174 } 00175 else 00176 { 00177 struct sockaddr_in6 addr6; 00178 addr6 = _get_addr6(port); 00179 if (bind(s,(struct sockaddr*)&addr6, (int)sizeof(addr6)) == -1) 00180 throw BindError("Bind error", HERE); 00181 } 00182 #endif 00183 return s; 00184 } 00185 00186 void NetSocket::_connect(int socket, int port, 00187 const std::string& host) const 00188 { 00189 #ifdef IPV6_ENABLED 00190 if (_version == V4) 00191 { 00192 #endif 00193 struct sockaddr_in addr; 00194 addr = _get_addr(host, port); 00195 if (connect(socket, (struct sockaddr *)&addr, 00196 sizeof (addr)) < 0) 00197 throw ConnectError("Unable to connect", HERE); 00198 #ifdef IPV6_ENABLED 00199 } 00200 else 00201 { 00202 struct sockaddr_in6 addr6; 00203 addr6 = _get_addr6(host, port); 00204 if (connect(socket, (struct sockaddr *)&addr6, 00205 sizeof (addr6)) < 0) 00206 throw ConnectError("Unable to connect", HERE); 00207 } 00208 #endif 00209 } 00210 00211 int NetSocket::_accept(int port, int socket) const 00212 { 00213 #ifdef LIBSOCKET_WIN 00214 int size; 00215 #else 00216 socklen_t size; 00217 #endif 00218 int s; 00219 struct sockaddr_in addr; 00220 #ifdef IPV6_ENABLED 00221 struct sockaddr_in6 addr6; 00222 00223 if (_version == V4) 00224 { 00225 #endif 00226 addr = _get_addr(port); 00227 size = sizeof(addr); 00228 s = accept(socket, (struct sockaddr*)&addr, &size); 00229 #ifdef IPV6_ENABLED 00230 } 00231 else 00232 { 00233 addr6 = _get_addr6(port); 00234 size = sizeof(addr6); 00235 s = accept(socket, (struct sockaddr*)&addr6, &size); 00236 } 00237 #endif 00238 if (s < 0) 00239 throw AcceptError("Accept Error", HERE); 00240 return s; 00241 } 00242 00243 std::string NetSocket::_get_ip(int port, int socket) const 00244 { 00245 struct sockaddr_in addr; 00246 #ifdef LIBSOCKET_WIN 00247 int size; 00248 #else 00249 socklen_t size; 00250 #endif 00251 00252 memset(&addr, '\0', sizeof(addr)); 00253 addr.sin_family = AF_INET; 00254 addr.sin_addr.s_addr = htonl(INADDR_ANY); 00255 addr.sin_port = htons(port); 00256 size = sizeof(addr); 00257 getpeername(socket, (struct sockaddr *)&addr, &size); 00258 return(std::string(inet_ntoa(addr.sin_addr))); 00259 } 00260 00261 std::string NetSocket::_read_line(int socket) 00262 { 00263 char chr[MAXPKTSIZE]; 00264 std::string str = ""; 00265 int res = 1, i; 00266 std::pair<int, int> delim; 00267 bool end = false; 00268 00269 if (socket < 0) 00270 throw NoConnection("No Socket", HERE); 00271 if (!_update_buffer(delim, i, str)) 00272 while (!end) 00273 { 00274 memset(chr, 0, MAXPKTSIZE); 00275 if (_state_timeout) 00276 _set_timeout(true, _socket, _state_timeout); 00277 if (_kind == UDP) 00278 #ifdef LIBSOCKET_WIN 00279 res = recv(socket, chr, MAXPKTSIZE, 0); 00280 #else 00281 res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC); 00282 #endif 00283 else 00284 #ifdef TLS 00285 if (_tls) 00286 res = gnutls_record_recv(_session, chr, MAXPKTSIZE); 00287 else 00288 #endif 00289 res = recv(socket, chr, MAXPKTSIZE, 0); 00290 if (_check_answer(res, str)) 00291 return str; 00292 _buffer += std::string(chr, res); 00293 if (_update_buffer(delim, i, str)) 00294 end = true; 00295 } 00296 _state_timeout = 0; 00297 return str; 00298 } 00299 00300 std::string NetSocket::_read_line(int socket, int& port, 00301 std::string& host) 00302 { 00303 char chr[MAXPKTSIZE]; 00304 std::string str = ""; 00305 int res = 1, i; 00306 std::pair<int, int> delim; 00307 struct sockaddr_in addr; 00308 #ifdef IPV6_ENABLED 00309 struct sockaddr_in6 addr6; 00310 #endif 00311 #ifdef LIBSOCKET_WIN 00312 int size; 00313 #else 00314 socklen_t size; 00315 #endif 00316 bool end = false; 00317 00318 #ifdef IPV6_ENABLED 00319 if (V4 == _version) 00320 #endif 00321 size = sizeof(addr); 00322 #ifdef IPV6_ENABLED 00323 else 00324 size = sizeof(addr6); 00325 #endif 00326 if (socket < 0) 00327 throw NoConnection("No Socket", HERE); 00328 if (!_update_buffer(delim, i, str)) 00329 while (!end) 00330 { 00331 if (_state_timeout) 00332 _set_timeout(true, _socket, _state_timeout); 00333 if (_kind == UDP) 00334 { 00335 #ifdef LIBSOCKET_WIN 00336 int flags = 0; 00337 #else 00338 int flags = MSG_TRUNC; 00339 #endif 00340 00341 #ifdef IPV6_ENABLED 00342 if (V4 == _version) 00343 #endif 00344 res = recvfrom(socket, chr, MAXPKTSIZE, flags, 00345 (struct sockaddr *) &addr, &size); 00346 #ifdef IPV6_ENABLED 00347 else 00348 res = recvfrom(socket, chr, MAXPKTSIZE, flags, 00349 (struct sockaddr *) &addr6, &size); 00350 #endif 00351 } 00352 else 00353 { 00354 #ifdef TLS 00355 if (_tls) 00356 res = gnutls_record_recv(_session, chr, MAXPKTSIZE); 00357 else 00358 #endif 00359 res = recvfrom(socket, chr, MAXPKTSIZE, 0, NULL, 0); 00360 #ifdef IPV6_ENABLED 00361 if (V4 == _version) 00362 { 00363 #endif 00364 if (getpeername(socket, (struct sockaddr *) &addr, &size) < 0) 00365 throw GetpeernameError("getpeername error", HERE); 00366 #ifdef IPV6_ENABLED 00367 } 00368 else 00369 if (getpeername(socket, (struct sockaddr *) &addr6, &size) < 0) 00370 throw GetpeernameError("getpeername error", HERE); 00371 #endif 00372 } 00373 if (_check_answer(res, str)) 00374 return str; 00375 _buffer += std::string(chr, res); 00376 if (_update_buffer(delim, i, str)) 00377 end = true; 00378 } 00379 #ifdef IPV6_ENABLED 00380 if (V4 == _version) 00381 { 00382 #endif 00383 host = std::string(inet_ntoa(addr.sin_addr)); 00384 port = ntohs(addr.sin_port); 00385 #ifdef IPV6_ENABLED 00386 } 00387 else 00388 { 00389 char buf[INET6_ADDRSTRLEN]; 00390 if (inet_ntop(AF_INET6, &addr6.sin6_addr, buf, INET6_ADDRSTRLEN) == 0) 00391 throw InetntopError("Not a valid address", HERE); 00392 host = std::string(buf); 00393 port = ntohs(addr6.sin6_port); 00394 } 00395 #endif 00396 _state_timeout = 0; 00397 return str; 00398 } 00399 00400 void NetSocket::_write_str(int socket, const std::string& str, 00401 const std::string& host, int port) const 00402 { 00403 struct sockaddr_in addr; 00404 #ifdef IPV6_ENABLED 00405 struct sockaddr_in6 addr6; 00406 #endif 00407 int res = 1; 00408 const char *buf = str.c_str(); 00409 unsigned int count = 0; 00410 00411 #ifdef IPV6_ENABLED 00412 if (V4 == _version) 00413 #endif 00414 addr = _get_addr(host, port); 00415 #ifdef IPV6_ENABLED 00416 else 00417 addr6 = _get_addr6(host, port); 00418 #endif 00419 if (socket < 0) 00420 throw NoConnection("No Socket", HERE); 00421 while (res && count < str.size()) 00422 { 00423 #ifdef IPV6_ENABLED 00424 if (V4 == _version) 00425 #endif 00426 #ifdef TLS 00427 if (_tls) 00428 res = gnutls_record_send(_session, buf + count, str.size() - count); 00429 else 00430 #endif 00431 res = sendto(socket, buf + count, 00432 str.size() - count, SENDTO_FLAGS, 00433 (const struct sockaddr*)&addr, sizeof(_addr)); 00434 #ifdef IPV6_ENABLED 00435 else 00436 res = sendto(socket, buf + count, 00437 str.size() - count, SENDTO_FLAGS, 00438 (const struct sockaddr*)&addr6, sizeof(_addr6)); 00439 #endif 00440 if (res <= 0) 00441 throw ConnectionClosed("Connection Closed", HERE); 00442 count += res; 00443 } 00444 } 00445 00446 void NetSocket::_write_str_bin(int socket, const std::string& str, 00447 const std::string& host, int port) const 00448 { 00449 struct sockaddr_in addr; 00450 #ifdef IPV6_ENABLED 00451 struct sockaddr_in6 addr6; 00452 #endif 00453 int res = 1; 00454 unsigned int count = 0; 00455 #ifdef LIBSOCKET_WIN 00456 char* buf = new char[str.size() + 2]; 00457 #else 00458 char buf[str.size() + 2]; 00459 #endif 00460 00461 buf[0] = str.size() / 256; 00462 buf[1] = str.size() % 256; 00463 memcpy(buf + 2, str.c_str(), str.size()); 00464 #ifdef IPV6_ENABLED 00465 if (V4 == _version) 00466 #endif 00467 addr = _get_addr(host, port); 00468 #ifdef IPV6_ENABLED 00469 else 00470 addr6 = _get_addr6(host, port); 00471 #endif 00472 if (socket < 0) 00473 throw NoConnection("No Socket", HERE); 00474 while (res && count < str.size() + 2) 00475 { 00476 #ifdef IPV6_ENABLED 00477 if (V4 == _version) 00478 #endif 00479 #ifdef TLS 00480 if (_tls) 00481 res = gnutls_record_send(_session, buf + count, str.size() + 2 - count); 00482 else 00483 #endif 00484 res = sendto(socket, buf + count, str.size() + 2 - count, 00485 SENDTO_FLAGS, 00486 (const struct sockaddr*)&addr, sizeof(_addr)); 00487 #ifdef IPV6_ENABLED 00488 else 00489 res = sendto(socket, buf + count, str.size() + 2 - count, 00490 SENDTO_FLAGS, 00491 (const struct sockaddr*)&addr6, sizeof(_addr6)); 00492 #endif 00493 if (res <= 0) 00494 throw ConnectionClosed("Connection Closed", HERE); 00495 count += res; 00496 } 00497 #ifdef LIBSOCKET_WIN 00498 delete[] buf; 00499 #endif 00500 } 00501 00502 void NetSocket::writeto(const std::string& str, 00503 const std::string& host, int port) 00504 { 00505 if (_proto_kind == binary) 00506 _write_str_bin(_socket, str, host, port); 00507 else 00508 _write_str(_socket, str, host, port); 00509 } 00510 00511 std::string NetSocket::read(int& port, std::string& host) 00512 { 00513 if (_proto_kind == binary) 00514 return _read_line_bin(_socket, port, host, 0); 00515 else 00516 return _read_line(_socket, port, host); 00517 } 00518 00519 std::string NetSocket::read(int& port, std::string& host, int timeout) 00520 { 00521 if (_proto_kind == binary) 00522 { 00523 _set_timeout(true, _socket, timeout); 00524 return _read_line_bin(_socket, port, host, 0); 00525 } 00526 else 00527 { 00528 _state_timeout = timeout; 00529 return _read_line(_socket, port, host); 00530 } 00531 } 00532 00533 std::string NetSocket::read() 00534 { 00535 if (_proto_kind == binary) 00536 return _read_line_bin(_socket, 0); 00537 else 00538 return _read_line(_socket); 00539 } 00540 00541 std::string NetSocket::read(int timeout) 00542 { 00543 if (_proto_kind == binary) 00544 { 00545 _set_timeout(true, _socket, timeout); 00546 return _read_line_bin(_socket, 0); 00547 } 00548 else 00549 { 00550 _state_timeout = timeout; 00551 return _read_line(_socket); 00552 } 00553 } 00554 00555 std::string NetSocket::readn(int& port, std::string& host, 00556 unsigned int size) 00557 { 00558 // _read_line_bin is bufferised with the same buffer as textual 00559 // protocols, so this function can be used for binary and text 00560 // protocols. 00561 return _read_line_bin(_socket, port, host, size); 00562 } 00563 00564 std::string NetSocket::readn(int& port, std::string& host, int timeout, 00565 unsigned int size) 00566 { 00567 if (!size || size > _buffer.size()) 00568 _set_timeout(true, _socket, timeout); 00569 // _read_line_bin is bufferised with the same buffer as textual 00570 // protocols, so this function can be used for binary and text 00571 // protocols. 00572 return _read_line_bin(_socket, port, host, size); 00573 } 00574 00575 std::string NetSocket::readn(unsigned int size) 00576 { 00577 // _read_line_bin is bufferised with the same buffer as textual 00578 // protocols, so this function can be used for binary and text 00579 // protocols. 00580 return _read_line_bin(_socket, size); 00581 } 00582 00583 std::string NetSocket::readn(int timeout, unsigned int size) 00584 { 00585 if (!size || size > _buffer.size()) 00586 _set_timeout(true, _socket, timeout); 00587 // _read_line_bin is bufferised with the same buffer as textual 00588 // protocols, so this function can be used for binary and text 00589 // protocols. 00590 return _read_line_bin(_socket, size); 00591 } 00592 }