00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "osdetect.h"
00029
00031 #if OS_TYPE == OS_WIN32
00032 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00033 #include <winsock2.h>
00034 #endif
00035 #endif
00036
00037 #include "xml/socket.h"
00038 #include "base/date.h"
00039 #include "base/list.hpp"
00040
00041 BEGIN_TERIMBER_NAMESPACE
00042 #pragma pack(4)
00043
00044 terimber_socket::terimber_socket(int num) :
00045 _number(num)
00046 {
00047 memset(&_addr, 0, sizeof(sockaddr_in));
00048 }
00049
00050 terimber_socket::~terimber_socket()
00051 {
00052 close();
00053 }
00054
00055
00056 void
00057 terimber_socket::set_options(int number)
00058 {
00059 linger lingerStruct;
00060 lingerStruct.l_onoff = 1;
00061 lingerStruct.l_linger = 0;
00062 ::setsockopt(number, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct));
00063
00064
00065 int noDelay = 1;
00066 ::setsockopt(number, IPPROTO_TCP, TCP_NODELAY, (const char*)&noDelay, sizeof(noDelay));
00067
00068 int keepAlive = 1;
00069 ::setsockopt(number, SOL_SOCKET, SO_KEEPALIVE, (const char*)&keepAlive, sizeof(keepAlive));
00070
00071
00072 int reUse = 1;
00073 ::setsockopt(number, SOL_SOCKET, SO_REUSEADDR, (const char*)&reUse, sizeof(reUse));
00074
00075 }
00076
00077
00078 int
00079 terimber_socket::resolve_address(const char* str, ub2_t port, sockaddr_in& addr)
00080 {
00081 in_addr ipAddr;
00082 if (str)
00083 {
00084 bool askDNS = false;
00085 for (const char* s = str; *s ; ++s)
00086 if (!isdigit( *s ) && *s != '.')
00087 {
00088 askDNS = true;
00089 break;
00090 }
00091
00092 if (askDNS)
00093 {
00094 struct hostent* host = gethostbyname(str);
00095 if( host == 0 )
00096 return WSAEFAULT;
00097 memcpy(&ipAddr, host->h_addr, host->h_length);
00098 }
00099 else
00100 {
00101 ipAddr.s_addr = inet_addr(str);
00102 if (ipAddr.s_addr == INADDR_NONE)
00103 return WSAEFAULT;
00104 }
00105 }
00106 else
00107 ipAddr.s_addr = htonl(INADDR_LOOPBACK);
00108
00109 memset(&addr, 0, sizeof(sockaddr_in));
00110 addr.sin_family = AF_INET;
00111 addr.sin_port = htons(port);
00112 addr.sin_addr = ipAddr;
00113 return 0;
00114 }
00115
00116
00117 void
00118 terimber_socket::set_send_timeout(int number, size_t timeout)
00119 {
00120 #if OS_TYPE == OS_WIN32
00121 size_t
00122 #else
00123 timeval
00124 #endif
00125 timeout_;
00126 if (timeout == INFINITE)
00127 {
00128 #if OS_TYPE == OS_WIN32
00129 timeout_ = 0;
00130 #else
00131 timeout_.tv_sec = timeout_.tv_usec = 0;
00132 #endif
00133 }
00134 else
00135 {
00136 #if OS_TYPE == OS_WIN32
00137 timeout_ = timeout;
00138 #else
00139 timeout_.tv_sec = timeout / 1000;
00140 timeout_.tv_usec = (timeout % 1000) * 1000 + 1;
00141 #endif
00142 }
00143
00144 ::setsockopt(number, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout_, sizeof(timeout_));
00145 }
00146
00147
00148 void
00149 terimber_socket::set_recv_timeout(int number, size_t timeout)
00150 {
00151 #if OS_TYPE == OS_WIN32
00152 size_t
00153 #else
00154 timeval
00155 #endif
00156 timeout_;
00157 if (timeout == INFINITE)
00158 {
00159 #if OS_TYPE == OS_WIN32
00160 timeout_ = 0;
00161 #else
00162 timeout_.tv_sec = timeout_.tv_usec = 0;
00163 #endif
00164 }
00165 else
00166 {
00167 #if OS_TYPE == OS_WIN32
00168 timeout_ = timeout;
00169 #else
00170 timeout_.tv_sec = timeout / 1000;
00171 timeout_.tv_usec = (timeout % 1000) * 1000 + 1;
00172 #endif
00173 }
00174
00175 ::setsockopt(number, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout_, sizeof(timeout_));
00176 }
00177
00178 bool
00179 terimber_socket::close()
00180 {
00181 if (INVALID_SOCKET == _number)
00182 return false;
00183
00184 static char rbuf[512];
00185
00186
00187 #if OS_TYPE == OS_WIN32
00188 ::shutdown(_number, SD_SEND);
00189 #else
00190 ::shutdown(_number, SHUT_WR);
00191 #endif
00192
00193
00194 fd_set recv_set;
00195 FD_ZERO(&recv_set);
00196 FD_SET(_number, &recv_set);
00197
00198 struct timeval timeout_val = {0, 1000};
00199 int res = 0;
00200
00201 do
00202 {
00203 res = ::select((int)_number + 1, &recv_set, 0, 0, &timeout_val);
00204
00205 if (res)
00206 {
00207 res = ::recv(_number, rbuf, 512, 0);
00208 if (res > 0 && res < 512)
00209 break;
00210 }
00211 }
00212 while (res > 0);
00213
00214
00215 #if OS_TYPE == OS_WIN32
00216 ::shutdown(_number, SD_RECEIVE);
00217
00218 ::closesocket(_number);
00219 #else
00220 ::shutdown(_number, SHUT_RD);
00221
00222 ::close(_number);
00223 #endif
00224 _number = INVALID_SOCKET;
00225 memset(&_addr, 0, sizeof(sockaddr_in));
00226 return true;
00227 }
00228
00229 bool
00230 terimber_socket::connect()
00231 {
00232 if (INVALID_SOCKET == _number)
00233 {
00234
00235 if (INVALID_SOCKET == (_number = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
00236 return false;
00237
00238 set_options((int)_number);
00239
00240
00241 if (::connect(_number, (struct sockaddr*)&_addr, sizeof(struct sockaddr_in)))
00242 {
00243 close();
00244 return false;
00245 }
00246 else
00247 return true;
00248 }
00249 else
00250 return false;
00251 }
00252
00253 int
00254 terimber_socket::send(const char* data, size_t len, size_t& timeout)
00255 {
00256 int ret = 0;
00257
00258 if (INVALID_SOCKET == _number)
00259 return WSAENOTSOCK;
00260
00261 fd_set send_set;
00262 date local_time;
00263 size_t shift = 0;
00264
00265 for (;;)
00266 {
00267 FD_ZERO(&send_set);
00268 FD_SET(_number, &send_set);
00269
00270 struct timeval wait = {(long)timeout / 1000, (long)timeout % 1000 * 1000};
00271 ret = ::select((int)_number + 1, 0, &send_set, 0, &wait);
00272
00273 if (!ret)
00274 return WSAETIMEDOUT;
00275
00276 if (SOCKET_ERROR == ret)
00277 return ret;
00278
00279 ret = ::send((int)_number, data + shift, (int)len, 0 );
00280
00281 if (SOCKET_ERROR == ret)
00282 return ret;
00283
00284 if (!ret)
00285 return WSAECONNRESET;
00286 else if (ret == len)
00287 break;
00288 else
00289 len -= ret, shift += ret;
00290
00291 if ((int)len < 0)
00292 return WSAEMSGSIZE;
00293
00294 timeout -= (size_t)date().get_difference(local_time);
00295 if ((int)timeout < 0)
00296 return WSAETIMEDOUT;
00297 }
00298
00299 return 0;
00300 }
00301
00302
00303 int
00304 terimber_socket::receive(char* data, size_t len, size_t& timeout)
00305 {
00306 int ret = 0;
00307
00308 if (INVALID_SOCKET == _number)
00309 return WSAENOTSOCK;
00310
00311 fd_set rec_set;
00312 date local_time;
00313 size_t shift = 0;
00314
00315 for (;;)
00316 {
00317 FD_ZERO(&rec_set);
00318 FD_SET(_number, &rec_set);
00319
00320 if (timeout != INFINITE)
00321 {
00322 struct timeval timeout_val = {(long)timeout / 1000, (long)timeout % 1000 * 1000 };
00323 ret = ::select((int)_number + 1, &rec_set, 0, 0, &timeout_val);
00324 }
00325 else
00326 {
00327 ret = ::select((int)_number + 1, &rec_set, 0, 0, 0);
00328 }
00329
00330 if (!ret)
00331 return WSAETIMEDOUT;
00332
00333 if (SOCKET_ERROR == ret)
00334 return ret;
00335
00336
00337
00338 unsigned long arg = 0;
00339
00340 #if OS_TYPE == OS_WIN32
00341 ret = ::ioctlsocket(_number, FIONREAD, &arg);
00342 #else
00343 ret = ::ioctl(_number, FIONREAD, &arg);
00344 #endif
00345
00346 if (SOCKET_ERROR == ret)
00347 return ret;
00348
00349 ret = ::recv((int)_number, data + shift, (int)__min(len, (size_t)arg), 0);
00350
00351 if (SOCKET_ERROR == ret)
00352 return ret;
00353
00354 if (!ret)
00355 return WSAECONNRESET;
00356 else if (ret == len)
00357 break;
00358 else
00359 len -= ret, shift += ret;
00360
00361 if (timeout != INFINITE)
00362 {
00363 timeout -= (size_t)date().get_difference(local_time);
00364 if ((int)timeout < 0)
00365 return WSAETIMEDOUT;
00366 }
00367 }
00368
00369 return 0;
00370 }
00371
00372
00373 int
00374 terimber_socket::receive_whatever(char* data, size_t len, size_t& timeout, size_t& rlen)
00375 {
00376 int ret = 0;
00377
00378 if (INVALID_SOCKET == _number)
00379 return WSAENOTSOCK;
00380
00381 fd_set rec_set;
00382 date local_time;
00383 rlen = 0;
00384
00385 FD_ZERO(&rec_set);
00386 FD_SET(_number, &rec_set);
00387
00388 if (timeout != INFINITE)
00389 {
00390 struct timeval timeout_val = {(long)timeout / 1000, (long)timeout % 1000 * 1000 };
00391 ret = ::select((int)_number + 1, &rec_set, 0, 0, &timeout_val);
00392 }
00393 else
00394 {
00395 ret = ::select((int)_number + 1, &rec_set, 0, 0, 0);
00396 }
00397
00398 if (!ret)
00399 return WSAETIMEDOUT;
00400
00401 if (SOCKET_ERROR == ret)
00402 return ret;
00403
00404
00405
00406 unsigned long arg = 0;
00407
00408 #if OS_TYPE == OS_WIN32
00409 ret = ::ioctlsocket(_number, FIONREAD, &arg);
00410 #else
00411 ret = ::ioctl(_number, FIONREAD, &arg);
00412 #endif
00413
00414 if (SOCKET_ERROR == ret)
00415 return ret;
00416
00417
00418 if (!len)
00419 return arg != 0 ? 0 : WSAEFAULT;
00420
00421 ret = ::recv((int)_number, data, (int)__min(len, (size_t)arg), 0);
00422
00423 if (SOCKET_ERROR == ret)
00424 return ret;
00425
00426 if (!ret)
00427 return WSAECONNRESET;
00428 else
00429 rlen = ret;
00430
00431 return 0;
00432 }
00433
00434 int
00435 terimber_socket::set_invalid()
00436 {
00437 int number = (int)_number;
00438 _number = INVALID_SOCKET;
00439 return number;
00440 }
00441
00442 bool
00443 terimber_socket::is_invalid() const
00444 {
00445 return _number == INVALID_SOCKET;
00446 }
00447
00448 #pragma pack()
00449 END_TERIMBER_NAMESPACE