PageRenderTime 71ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/system/jlib/jsocket.cpp

https://github.com/emuharemagic/HPCC-Platform
C++ | 5993 lines | 5423 code | 459 blank | 111 comment | 863 complexity | c2caf370a2f41ff6eb37f88a13a46a5a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. // New IPv6 Version - IN PROGRESS
  14. /*
  15. TBD IPv6 connect
  16. multicast
  17. look at loopback
  18. */
  19. #include "platform.h"
  20. #ifdef _VER_C5
  21. #include <clwclib.h>
  22. #else
  23. #include "platform.h"
  24. #include <stdio.h>
  25. #endif
  26. #include <algorithm>
  27. #ifdef _WIN32
  28. #define WIN32_LEAN_AND_MEAN
  29. #include <windows.h>
  30. #include <winsock2.h>
  31. #include <ws2tcpip.h>
  32. #include <signal.h>
  33. #else
  34. #include <sys/types.h>
  35. #include <sys/socket.h>
  36. #include <netinet/tcp.h>
  37. #include <netinet/in.h>
  38. #include <arpa/inet.h>
  39. #include <stddef.h>
  40. #include <errno.h>
  41. #include <net/if.h>
  42. #endif
  43. #include <limits.h>
  44. #include "jmutex.hpp"
  45. #include "jsocket.hpp"
  46. #include "jexcept.hpp"
  47. #include "jio.hpp"
  48. #include "jmisc.hpp"
  49. #include "jthread.hpp"
  50. #include "jqueue.tpp"
  51. #include "jtime.hpp"
  52. #include "jprop.hpp"
  53. #include "jregexp.hpp"
  54. #include "jdebug.hpp"
  55. #include "build-config.h"
  56. // epoll only with linux
  57. #ifndef __linux__
  58. # undef _HAS_EPOLL_SUPPORT
  59. #else
  60. # define _HAS_EPOLL_SUPPORT
  61. # ifdef _HAS_EPOLL_SUPPORT
  62. # include <unistd.h>
  63. # include <sys/epoll.h>
  64. # ifndef EPOLLRDHUP
  65. // Centos 5.x bug - epoll.h does not define but its in the kernel
  66. # define EPOLLRDHUP 0x2000
  67. # endif
  68. # endif
  69. #endif
  70. // various options
  71. #define CONNECT_TIMEOUT_REFUSED_WAIT 1000 // maximum to sleep on connect_timeout
  72. #define TRACE_SLOW_BLOCK_TRANSFER
  73. #define DEFAULT_CONNECT_TIME (100*1000) // for connect_wait
  74. #ifndef _WIN32
  75. #define BLOCK_POLLED_SINGLE_CONNECTS // NB this is much slower in windows
  76. #define CENTRAL_NODE_RANDOM_DELAY
  77. #else
  78. #define USERECVSEM // to singlethread BF_SYNC_TRANSFER_PUSH
  79. #endif
  80. #ifdef _DEBUG
  81. //#define SOCKTRACE
  82. //#define EPOLLTRACE
  83. #endif
  84. #ifdef _TESTING
  85. #define _TRACE
  86. #endif
  87. #ifdef _TRACE
  88. #define THROWJSOCKEXCEPTION(exc) \
  89. { StringBuffer msg; \
  90. msg.appendf("Target: %s, Raised in: %s, line %d",tracename ,__FILE__, __LINE__); \
  91. IJSOCK_Exception *e = new SocketException(exc,msg.str());\
  92. throw e; }
  93. #define THROWJSOCKEXCEPTION2(exc) \
  94. { StringBuffer msg; \
  95. msg.appendf("Raised in: %s, line %d",__FILE__, __LINE__); \
  96. IJSOCK_Exception *e = new SocketException(exc,msg.str());\
  97. throw e; }
  98. #define LOGERR(err,ref,info) LogErr(err,ref,info,__LINE__,NULL)
  99. #define LOGERR2(err,ref,info) LogErr(err,ref,info,__LINE__,tracename)
  100. #else
  101. #define THROWJSOCKEXCEPTION(exc) \
  102. { IJSOCK_Exception *e = new SocketException(exc);\
  103. throw e; }
  104. #define THROWJSOCKEXCEPTION2(exc) THROWJSOCKEXCEPTION(exc)
  105. #define LOGERR(err,ref,info)
  106. #define LOGERR2(err,ref,info)
  107. #endif
  108. JSocketStatistics STATS;
  109. static bool IP4only=false; // slighly faster if we know no IPv6
  110. static bool IP6preferred=false; // e.g. for DNS and socket create
  111. IpSubNet PreferredSubnet(NULL,NULL); // set this if you prefer a particular subnet for debugging etc
  112. // e.g. PreferredSubnet("192.168.16.0", "255.255.255.0")
  113. static atomic_t pre_conn_unreach_cnt = ATOMIC_INIT(0); // global count of pre_connect() ENETUNREACH error
  114. #define IPV6_SERIALIZE_PREFIX (0x00ff00ff)
  115. inline void LogErr(unsigned err,unsigned ref,const char *info,unsigned lineno,const char *tracename)
  116. {
  117. if (err)
  118. PROGLOG("jsocket(%d,%d)%s%s err = %d%s%s",ref,lineno,
  119. (info&&*info)?" ":"",(info&&*info)?info:"",err,
  120. (tracename&&*tracename)?" : ":"",(tracename&&*tracename)?tracename:"");
  121. }
  122. class jlib_thrown_decl SocketException: public CInterface, public IJSOCK_Exception
  123. {
  124. public:
  125. IMPLEMENT_IINTERFACE;
  126. SocketException(int code,const char *_msg=NULL) : errcode(code)
  127. {
  128. if (_msg)
  129. msg = strdup(_msg);
  130. else
  131. msg = NULL;
  132. };
  133. ~SocketException() { free(msg); }
  134. int errorCode() const { return errcode; }
  135. static StringBuffer & geterrormessage(int err,StringBuffer &str)
  136. {
  137. switch (err) {
  138. case JSOCKERR_ok: return str.append("ok");
  139. case JSOCKERR_not_opened: return str.append("socket not opened");
  140. case JSOCKERR_bad_address: return str.append("bad address");
  141. case JSOCKERR_connection_failed: return str.append("connection failed");
  142. case JSOCKERR_broken_pipe: return str.append("connection is broken");
  143. case JSOCKERR_graceful_close: return str.append("connection closed other end");
  144. case JSOCKERR_invalid_access_mode: return str.append("invalid access mode");
  145. case JSOCKERR_timeout_expired: return str.append("timeout expired");
  146. case JSOCKERR_port_in_use: return str.append("port in use");
  147. case JSOCKERR_cancel_accept: return str.append("cancel accept");
  148. case JSOCKERR_connectionless_socket: return str.append("connectionless socket");
  149. case JSOCKERR_handle_too_large: return str.append("handle too large");
  150. case JSOCKERR_bad_netaddr: return str.append("bad net addr");
  151. case JSOCKERR_ipv6_not_implemented: return str.append("IPv6 not implemented");
  152. // OS errors
  153. #ifdef _WIN32
  154. case WSAEINTR: return str.append("WSAEINTR(10004) - Interrupted system call.");
  155. case WSAEBADF: return str.append("WSAEBADF(10009) - Bad file number.");
  156. case WSAEACCES: return str.append("WSAEACCES(10013) - Permission denied.");
  157. case WSAEFAULT: return str.append("WSAEFAULT(10014) - Bad address.");
  158. case WSAEINVAL: return str.append("WSAEINVAL(10022) - Invalid argument.");
  159. case WSAEMFILE: return str.append("WSAEMFILE(10024) - Too many open files.");
  160. case WSAEWOULDBLOCK: return str.append("WSAEWOULDBLOCK(10035) - Operation would block.");
  161. case WSAEINPROGRESS: return str.append("WSAEINPROGRESS(10036) - Operation now in progress.");
  162. case WSAEALREADY: return str.append("WSAEALREADY(10037) - Operation already in progress.");
  163. case WSAENOTSOCK: return str.append("WSAENOTSOCK(10038) - Socket operation on nonsocket.");
  164. case WSAEDESTADDRREQ: return str.append("WSAEDESTADDRREQ(10039) - Destination address required.");
  165. case WSAEMSGSIZE: return str.append("WSAEMSGSIZE(10040) - Message too long.");
  166. case WSAEPROTOTYPE: return str.append("WSAEPROTOTYPE(10041) - Protocol wrong type for socket.");
  167. case WSAENOPROTOOPT: return str.append("WSAENOPROTOOPT(10042) - Protocol not available.");
  168. case WSAEPROTONOSUPPORT: return str.append("WSAEPROTONOSUPPORT(10043) - Protocol not supported.");
  169. case WSAESOCKTNOSUPPORT: return str.append("WSAESOCKTNOSUPPORT(10044) - Socket type not supported.");
  170. case WSAEOPNOTSUPP: return str.append("WSAEOPNOTSUPP(10045) - Operation not supported on socket.");
  171. case WSAEPFNOSUPPORT: return str.append("WSAEPFNOSUPPORT(10046) - Protocol family not supported.");
  172. case WSAEAFNOSUPPORT: return str.append("WSAEAFNOSUPPORT(10047) - Address family not supported by protocol family.");
  173. case WSAEADDRINUSE: return str.append("WSAEADDRINUSE(10048) - Address already in use.");
  174. case WSAEADDRNOTAVAIL: return str.append("WSAEADDRNOTAVAIL(10049) - Cannot assign requested address.");
  175. case WSAENETDOWN: return str.append("WSAENETDOWN(10050) - Network is down.");
  176. case WSAENETUNREACH: return str.append("WSAENETUNREACH(10051) - Network is unreachable.");
  177. case WSAENETRESET: return str.append("WSAENETRESET(10052) - Network dropped connection on reset.");
  178. case WSAECONNABORTED: return str.append("WSAECONNABORTED(10053) - Software caused connection abort.");
  179. case WSAECONNRESET: return str.append("WSAECONNRESET(10054) - Connection reset by peer.");
  180. case WSAENOBUFS: return str.append("WSAENOBUFS(10055) - No buffer space available.");
  181. case WSAEISCONN: return str.append("WSAEISCONN(10056) - Socket is already connected.");
  182. case WSAENOTCONN: return str.append("WSAENOTCONN(10057) - Socket is not connected.");
  183. case WSAESHUTDOWN: return str.append("WSAESHUTDOWN(10058) - Cannot send after socket shutdown.");
  184. case WSAETOOMANYREFS: return str.append("WSAETOOMANYREFS(10059) - Too many references: cannot splice.");
  185. case WSAETIMEDOUT: return str.append("WSAETIMEDOUT(10060) - Connection timed out.");
  186. case WSAECONNREFUSED: return str.append("WSAECONNREFUSED(10061) - Connection refused.");
  187. case WSAELOOP: return str.append("WSAELOOP(10062) - Too many levels of symbolic links.");
  188. case WSAENAMETOOLONG: return str.append("WSAENAMETOOLONG(10063) - File name too long.");
  189. case WSAEHOSTDOWN: return str.append("WSAEHOSTDOWN(10064) - Host is down.");
  190. case WSAEHOSTUNREACH: return str.append("WSAEHOSTUNREACH(10065) - No route to host.");
  191. case WSASYSNOTREADY: return str.append("WSASYSNOTREADY(10091) - The network subsystem is unusable.");
  192. case WSAVERNOTSUPPORTED: return str.append("WSAVERNOTSUPPORTED(10092) - The Windows Sockets DLL cannot support this application.");
  193. case WSANOTINITIALISED: return str.append("WSANOTINITIALISED(10093) - Winsock not initialized.");
  194. case WSAEDISCON: return str.append("WSAEDISCON(10101) - Disconnect.");
  195. case WSAHOST_NOT_FOUND: return str.append("WSAHOST_NOT_FOUND(11001) - Host not found.");
  196. case WSATRY_AGAIN: return str.append("WSATRY_AGAIN(11002) - Nonauthoritative host not found.");
  197. case WSANO_RECOVERY: return str.append("WSANO_RECOVERY(11003) - Nonrecoverable error.");
  198. case WSANO_DATA: return str.append("WSANO_DATA(11004) - Valid name, no data record of requested type.");
  199. #else
  200. case ENOTSOCK: return str.append("ENOTSOCK - Socket operation on non-socket ");
  201. case EDESTADDRREQ: return str.append("EDESTADDRREQ - Destination address required ");
  202. case EMSGSIZE: return str.append("EMSGSIZE - Message too long ");
  203. case EPROTOTYPE: return str.append("EPROTOTYPE - Protocol wrong type for socket ");
  204. case ENOPROTOOPT: return str.append("ENOPROTOOPT - Protocol not available ");
  205. case EPROTONOSUPPORT: return str.append("EPROTONOSUPPORT - Protocol not supported ");
  206. case ESOCKTNOSUPPORT: return str.append("ESOCKTNOSUPPORT - Socket type not supported ");
  207. case EOPNOTSUPP: return str.append("EOPNOTSUPP - Operation not supported on socket ");
  208. case EPFNOSUPPORT: return str.append("EPFNOSUPPORT - Protocol family not supported ");
  209. case EAFNOSUPPORT: return str.append("EAFNOSUPPORT - Address family not supported by protocol family ");
  210. case EADDRINUSE: return str.append("EADDRINUSE - Address already in use ");
  211. case EADDRNOTAVAIL: return str.append("EADDRNOTAVAIL - Can't assign requested address ");
  212. case ENETDOWN: return str.append("ENETDOWN - Network is down ");
  213. case ENETUNREACH: return str.append("ENETUNREACH - Network is unreachable ");
  214. case ENETRESET: return str.append("ENETRESET - Network dropped connection because of reset ");
  215. case ECONNABORTED: return str.append("ECONNABORTED - Software caused connection abort ");
  216. case ECONNRESET: return str.append("ECONNRESET - Connection reset by peer ");
  217. case ENOBUFS: return str.append("ENOBUFS - No buffer space available ");
  218. case EISCONN: return str.append("EISCONN - Socket is already connected ");
  219. case ENOTCONN: return str.append("ENOTCONN - Socket is not connected ");
  220. case ESHUTDOWN: return str.append("ESHUTDOWN - Can't send after socket shutdown ");
  221. case ETOOMANYREFS: return str.append("ETOOMANYREFS - Too many references: can't splice ");
  222. case ETIMEDOUT: return str.append("ETIMEDOUT - Connection timed out ");
  223. case ECONNREFUSED: return str.append("ECONNREFUSED - Connection refused ");
  224. case EHOSTDOWN: return str.append("EHOSTDOWN - Host is down ");
  225. case EHOSTUNREACH: return str.append("EHOSTUNREACH - No route to host ");
  226. case EWOULDBLOCK: return str.append("EWOULDBLOCK - operation already in progress");
  227. case EINPROGRESS: return str.append("EINPROGRESS - operation now in progress ");
  228. #endif
  229. }
  230. IException *ose = MakeOsException(err);
  231. ose->errorMessage(str);
  232. ose->Release();
  233. return str;
  234. }
  235. StringBuffer & errorMessage(StringBuffer &str) const
  236. {
  237. if (msg)
  238. return geterrormessage(errcode,str).append('\n').append(msg);
  239. return geterrormessage(errcode,str);
  240. }
  241. MessageAudience errorAudience() const
  242. {
  243. switch (errcode) {
  244. case JSOCKERR_port_in_use:
  245. return MSGAUD_operator;
  246. }
  247. return MSGAUD_user;
  248. }
  249. private:
  250. int errcode;
  251. char *msg;
  252. };
  253. IJSOCK_Exception *IPv6NotImplementedException(const char *filename,unsigned lineno)
  254. {
  255. StringBuffer msg;
  256. msg.appendf("%s(%d)",filename,lineno);
  257. return new SocketException(JSOCKERR_ipv6_not_implemented,msg.str());
  258. }
  259. struct MCASTREQ
  260. {
  261. struct in_addr imr_multiaddr; /* multicast group to join */
  262. struct in_addr imr_interface; /* interface to join on */
  263. MCASTREQ(const char *mcip)
  264. {
  265. imr_multiaddr.s_addr = inet_addr(mcip);
  266. imr_interface.s_addr = htonl(INADDR_ANY);
  267. }
  268. };
  269. #ifdef __APPLE__
  270. #ifndef MSG_NOSIGNAL
  271. #define MSG_NOSIGNAL 0x4000
  272. #endif
  273. #endif
  274. #if defined( _WIN32)
  275. #define T_SOCKET SOCKET
  276. #define T_FD_SET fd_set
  277. #define XFD_SETSIZE FD_SETSIZE
  278. #define ETIMEDOUT WSAETIMEDOUT
  279. #define ECONNREFUSED WSAECONNREFUSED
  280. #define XFD_ZERO(s) FD_ZERO(s)
  281. #define SEND_FLAGS 0
  282. #define BADSOCKERR(err) ((err==WSAEBADF)||(err==WSAENOTSOCK))
  283. #define CHECKSOCKRANGE(s)
  284. #elif defined(__FreeBSD__) || defined(__APPLE__)
  285. #define XFD_SETSIZE FD_SETSIZE
  286. #define T_FD_SET fd_set
  287. #define XFD_ZERO(s) FD_ZERO(s)
  288. #define T_SOCKET int
  289. #define SEND_FLAGS (MSG_NOSIGNAL)
  290. #define BADSOCKERR(err) ((err==EBADF)||(err==ENOTSOCK))
  291. #define CHECKSOCKRANGE(s)
  292. #else
  293. #define XFD_SETSIZE 32768
  294. struct xfd_set { __fd_mask fds_bits[XFD_SETSIZE / __NFDBITS]; }; // define our own
  295. // linux 64 bit
  296. #ifdef __linux__
  297. #ifdef __x86_64__
  298. #undef __FDMASK
  299. #define __FDMASK(d) (1UL << ((d) % __NFDBITS))
  300. #undef __FDELT
  301. #define __FDELT(d) ((d) / __NFDBITS)
  302. #undef __FD_SET
  303. #define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d))
  304. #undef __FD_ISSET
  305. #define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0)
  306. #endif
  307. #define CHECKSOCKRANGE(s) { if (s>=XFD_SETSIZE) THROWJSOCKEXCEPTION2(JSOCKERR_handle_too_large); }
  308. #endif
  309. // end 64 bit
  310. #define T_FD_SET xfd_set
  311. #define XFD_ZERO(s) memset(s,0,sizeof(xfd_set))
  312. #define T_SOCKET int
  313. #define SEND_FLAGS (MSG_NOSIGNAL)
  314. #define BADSOCKERR(err) ((err==EBADF)||(err==ENOTSOCK))
  315. #endif
  316. #ifdef CENTRAL_NODE_RANDOM_DELAY
  317. static SocketEndpointArray CentralNodeArray;
  318. #endif
  319. enum SOCKETMODE { sm_tcp_server, sm_tcp, sm_udp_server, sm_udp, sm_multicast_server, sm_multicast};
  320. class CSocket: public CInterface, public ISocket
  321. {
  322. public:
  323. IMPLEMENT_IINTERFACE;
  324. static CriticalSection crit;
  325. protected:
  326. friend class CSocketConnectWait;
  327. enum { ss_open, ss_shutdown, ss_close, ss_pre_open } state;
  328. T_SOCKET sock;
  329. char* hostname; // host address
  330. unsigned short hostport; // host port
  331. SOCKETMODE sockmode;
  332. IpAddress targetip;
  333. SocketEndpoint returnep; // set by set_return_addr
  334. MCASTREQ * mcastreq;
  335. size32_t nextblocksize;
  336. unsigned blockflags;
  337. unsigned blocktimeoutms;
  338. bool owned;
  339. enum {accept_not_cancelled, accept_cancel_pending, accept_cancelled} accept_cancel_state;
  340. bool in_accept;
  341. bool nonblocking;
  342. bool nagling;
  343. static unsigned connectingcount;
  344. #ifdef USERECVSEM
  345. static Semaphore receiveblocksem;
  346. bool receiveblocksemowned; // owned by this socket
  347. #endif
  348. #ifdef _TRACE
  349. char * tracename;
  350. #endif
  351. public:
  352. void open(int listen_queue_size,bool reuseports=false);
  353. bool connect_timeout( unsigned timeout, bool noexception);
  354. void connect_wait( unsigned timems);
  355. void udpconnect();
  356. void read(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read,unsigned timeoutsecs);
  357. void readtms(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read, unsigned timedelaysecs);
  358. void read(void* buf, size32_t size);
  359. size32_t write(void const* buf, size32_t size);
  360. size32_t write_multiple(unsigned num,void const**buf, size32_t *size);
  361. size32_t udp_write_to(SocketEndpoint &ep,void const* buf, size32_t size);
  362. void close();
  363. void errclose();
  364. bool connectionless() { return (sockmode!=sm_tcp)&&(sockmode!=sm_tcp_server); }
  365. void shutdown(unsigned mode);
  366. ISocket* accept(bool allowcancel);
  367. int wait_read(unsigned timeout);
  368. int wait_write(unsigned timeout);
  369. int name(char *name,size32_t namemax);
  370. int peer_name(char *name,size32_t namemax);
  371. SocketEndpoint &getPeerEndpoint(SocketEndpoint &ep);
  372. IpAddress & getPeerAddress(IpAddress &addr);
  373. void set_return_addr(int port,const char *name); // sets returnep
  374. void cancel_accept();
  375. size32_t get_max_send_size();
  376. bool set_nonblock(bool on=true);
  377. bool set_nagle(bool on);
  378. void set_linger(int lingersecs);
  379. void set_keep_alive(bool set);
  380. virtual void set_inherit(bool inherit=false);
  381. virtual bool check_connection();
  382. // Block functions
  383. void set_block_mode(unsigned flags,size32_t recsize=0,unsigned timeoutms=0);
  384. bool send_block(const void *blk,size32_t sz);
  385. size32_t receive_block_size();
  386. size32_t receive_block(void *blk,size32_t sz);
  387. size32_t get_send_buffer_size();
  388. void set_send_buffer_size(size32_t sz);
  389. bool join_multicast_group(SocketEndpoint &ep); // for udp multicast
  390. bool leave_multicast_group(SocketEndpoint &ep); // for udp multicast
  391. size32_t get_receive_buffer_size();
  392. void set_receive_buffer_size(size32_t sz);
  393. size32_t avail_read();
  394. int pre_connect(bool block);
  395. int post_connect();
  396. CSocket(const SocketEndpoint &_ep,SOCKETMODE smode,const char *name);
  397. CSocket(T_SOCKET new_sock,SOCKETMODE smode,bool _owned);
  398. virtual ~CSocket();
  399. unsigned OShandle()
  400. {
  401. return (unsigned)sock;
  402. }
  403. private:
  404. int closesock()
  405. {
  406. if (sock!=INVALID_SOCKET) {
  407. T_SOCKET s = sock;
  408. sock = INVALID_SOCKET;
  409. STATS.activesockets--;
  410. #ifdef SOCKTRACE
  411. PROGLOG("SOCKTRACE: Closing socket %x %d (%x)", s, s, this);
  412. #endif
  413. #ifdef _WIN32
  414. return ::closesocket(s);
  415. #else
  416. return ::close(s);
  417. #endif
  418. }
  419. else
  420. return 0;
  421. }
  422. };
  423. CriticalSection CSocket::crit;
  424. unsigned CSocket::connectingcount=0;
  425. #ifdef USERECVSEM
  426. Semaphore CSocket::receiveblocksem(2);
  427. #endif
  428. #ifdef _WIN32
  429. class win_socket_library
  430. {
  431. static bool initdone; // to prevent dependancy probs very early on (e.g. jlog)
  432. public:
  433. win_socket_library() { init(); }
  434. bool init()
  435. {
  436. if (initdone)
  437. return true;
  438. WSADATA wsa;
  439. if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
  440. if (WSAStartup(MAKEWORD(1, 1), &wsa) != 0) {
  441. MessageBox(NULL,"Failed to initialize windows sockets","JLib Socket Error",MB_OK);
  442. return false;
  443. }
  444. }
  445. initdone = true;
  446. return true;
  447. }
  448. ~win_socket_library()
  449. {
  450. WSACleanup();
  451. }
  452. };
  453. bool win_socket_library::initdone = false;
  454. static win_socket_library ws32_lib;
  455. #define ERRNO() WSAGetLastError()
  456. #define EADDRINUSE WSAEADDRINUSE
  457. #define EINTRCALL WSAEINTR
  458. #define ECONNRESET WSAECONNRESET
  459. #define ECONNABORTED WSAECONNABORTED
  460. #define ENOTCONN WSAENOTCONN
  461. #define EWOULDBLOCK WSAEWOULDBLOCK
  462. #define EINPROGRESS WSAEINPROGRESS
  463. #define ENETUNREACH WSAENETUNREACH
  464. #define ENOTSOCK WSAENOTSOCK
  465. struct j_sockaddr_in6 {
  466. short sin6_family; /* AF_INET6 */
  467. u_short sin6_port; /* Transport level port number */
  468. u_long sin6_flowinfo; /* IPv6 flow information */
  469. struct in_addr6 sin6_addr; /* IPv6 address */
  470. u_long sin6_scope_id; /* set of interfaces for a scope */
  471. };
  472. typedef union {
  473. struct sockaddr sa;
  474. struct j_sockaddr_in6 sin6;
  475. struct sockaddr_in sin;
  476. } J_SOCKADDR;
  477. #define DEFINE_SOCKADDR(name) J_SOCKADDR name; memset(&name,0,sizeof(J_SOCKADDR))
  478. static int _inet_pton(int af, const char* src, void* dst)
  479. {
  480. DEFINE_SOCKADDR(u);
  481. int address_length;
  482. switch (af) {
  483. case AF_INET:
  484. u.sin.sin_family = AF_INET;
  485. address_length = sizeof (u.sin);
  486. break;
  487. case AF_INET6:
  488. u.sin6.sin6_family = AF_INET6;
  489. address_length = sizeof (u.sin6);
  490. break;
  491. default:
  492. #ifdef EAFNOSUPPORT
  493. errno = EAFNOSUPPORT;
  494. #else
  495. errno = 52;
  496. #endif
  497. return -1;
  498. }
  499. ws32_lib.init();
  500. int ret = WSAStringToAddress ((LPTSTR) src, af, NULL, &u.sa, &address_length);
  501. if (ret == 0) {
  502. switch (af) {
  503. case AF_INET:
  504. memcpy (dst, &u.sin.sin_addr, sizeof (struct in_addr));
  505. break;
  506. case AF_INET6:
  507. memcpy (dst, &u.sin6.sin6_addr, sizeof (u.sin6.sin6_addr));
  508. break;
  509. }
  510. return 1;
  511. }
  512. errno = WSAGetLastError();
  513. // PROGLOG("errno = %d",errno);
  514. return 0;
  515. }
  516. static const char * _inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
  517. {
  518. /* struct sockaddr can't accomodate struct sockaddr_in6. */
  519. DEFINE_SOCKADDR(u);
  520. DWORD dstlen = cnt;
  521. size_t srcsize;
  522. memset(&u,0,sizeof(u));
  523. switch (af) {
  524. case AF_INET:
  525. u.sin.sin_family = AF_INET;
  526. u.sin.sin_addr = *(struct in_addr *) src;
  527. srcsize = sizeof (u.sin);
  528. break;
  529. case AF_INET6:
  530. u.sin6.sin6_family = AF_INET6;
  531. memcpy(&u.sin6.sin6_addr,src,sizeof(in_addr6));
  532. srcsize = sizeof (u.sin6);
  533. break;
  534. default:
  535. return NULL;
  536. }
  537. ws32_lib.init();
  538. if (WSAAddressToString (&u.sa, srcsize, NULL, dst, &dstlen) != 0) {
  539. errno = WSAGetLastError();
  540. return NULL;
  541. }
  542. return (const char *) dst;
  543. }
  544. int inet_aton (const char *name, struct in_addr *addr)
  545. {
  546. addr->s_addr = inet_addr (name);
  547. return (addr->s_addr == (u_long)-1)?1:0; // 255.255.255.255 has had it here
  548. }
  549. #else
  550. #define _inet_ntop inet_ntop
  551. #define _inet_pton inet_pton
  552. #define in_addr6 in6_addr
  553. typedef union {
  554. struct sockaddr sa;
  555. struct sockaddr_in6 sin6;
  556. struct sockaddr_in sin;
  557. } J_SOCKADDR;
  558. #define DEFINE_SOCKADDR(name) J_SOCKADDR name; memset(&name,0,sizeof(J_SOCKADDR))
  559. #define EINTRCALL EINTR
  560. #define ERRNO() (errno)
  561. #ifndef INADDR_NONE
  562. #define INADDR_NONE (-1)
  563. #endif
  564. #endif
  565. #ifndef INET6_ADDRSTRLEN
  566. #define INET6_ADDRSTRLEN 65
  567. #endif
  568. inline socklen_t setSockAddr(J_SOCKADDR &u, const IpAddress &ip,unsigned short port)
  569. {
  570. if (!IP6preferred) {
  571. if (ip.getNetAddress(sizeof(in_addr),&u.sin.sin_addr)==sizeof(in_addr)) {
  572. u.sin.sin_family = AF_INET;
  573. u.sin.sin_port = htons(port);
  574. return sizeof(u.sin);
  575. }
  576. }
  577. if (IP4only)
  578. IPV6_NOT_IMPLEMENTED();
  579. ip.getNetAddress(sizeof(in_addr6),&u.sin6.sin6_addr);
  580. u.sin6.sin6_family = AF_INET6;
  581. u.sin6.sin6_port = htons(port);
  582. return sizeof(u.sin6);
  583. }
  584. inline socklen_t setSockAddrAny(J_SOCKADDR &u, unsigned short port)
  585. {
  586. if (IP6preferred) {
  587. #ifdef _WIN32
  588. IN6ADDR_SETANY((PSOCKADDR_IN6)&u.sin6.sin6_addr);
  589. #else
  590. memcpy(&u.sin6.sin6_addr,&in6addr_any,sizeof(in_addr6));
  591. #endif
  592. u.sin6.sin6_family= AF_INET6;
  593. u.sin6.sin6_port = htons(port);
  594. return sizeof(u.sin6);
  595. }
  596. u.sin.sin_addr.s_addr = htonl(INADDR_ANY);
  597. u.sin.sin_family= AF_INET;
  598. u.sin.sin_port = htons(port);
  599. return sizeof(u.sin);
  600. }
  601. inline void getSockAddrEndpoint(const J_SOCKADDR &u, socklen_t ul, SocketEndpoint &ep)
  602. {
  603. if (ul==sizeof(u.sin)) {
  604. ep.setNetAddress(sizeof(in_addr),&u.sin.sin_addr);
  605. ep.port = htons(u.sin.sin_port);
  606. }
  607. else {
  608. ep.setNetAddress(sizeof(in_addr6),&u.sin6.sin6_addr);
  609. ep.port = htons(u.sin6.sin6_port);
  610. }
  611. }
  612. /* might need fcntl(F_SETFL), or ioctl(FIONBIO) */
  613. /* Posix.1g says fcntl */
  614. #if defined(O_NONBLOCK)
  615. bool CSocket::set_nonblock(bool on)
  616. {
  617. int flags = fcntl(sock, F_GETFL, 0);
  618. if (flags == -1)
  619. return nonblocking;
  620. if (on)
  621. flags |= O_NONBLOCK;
  622. else
  623. flags &= ~O_NONBLOCK;
  624. if (fcntl(sock, F_SETFL, flags)==0) {
  625. bool wasNonBlocking = nonblocking;
  626. nonblocking = on;
  627. return wasNonBlocking;
  628. }
  629. return nonblocking;
  630. }
  631. #else
  632. bool CSocket::set_nonblock(bool on)
  633. {
  634. #ifdef _WIN32
  635. u_long yes = on?1:0;
  636. if (ioctlsocket(sock, FIONBIO, &yes)==0) {
  637. #else
  638. int yes = on?1:0;
  639. if (ioctl(sock, FIONBIO, &yes)==0) {
  640. #endif
  641. bool wasNonBlocking = nonblocking;
  642. nonblocking = on;
  643. return wasNonBlocking;
  644. }
  645. return nonblocking;
  646. }
  647. #endif
  648. bool CSocket::set_nagle(bool on)
  649. {
  650. bool ret = nagling;
  651. nagling = on;
  652. int enabled = !on;
  653. if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enabled, sizeof(enabled)) != 0) {
  654. nagling = !on;
  655. }
  656. return ret;
  657. }
  658. void CSocket::set_inherit(bool inherit)
  659. {
  660. #ifndef _WIN32
  661. long flag = fcntl(sock, F_GETFD);
  662. if(inherit)
  663. flag &= ~FD_CLOEXEC;
  664. else
  665. flag |= FD_CLOEXEC;
  666. fcntl(sock, F_SETFD, flag);
  667. #endif
  668. }
  669. size32_t CSocket::avail_read()
  670. {
  671. #ifdef _WIN32
  672. u_long avail;
  673. if (ioctlsocket(sock, FIONREAD, &avail)==0)
  674. #else
  675. int avail;
  676. if (ioctl(sock, FIONREAD, &avail)==0)
  677. #endif
  678. return (size32_t)avail;
  679. int err = ERRNO();
  680. LOGERR2(err,1,"avail_read");
  681. return 0;
  682. }
  683. #define PRE_CONN_UNREACH_ELIM 100
  684. int CSocket::pre_connect (bool block)
  685. {
  686. assertex(hostname);
  687. DEFINE_SOCKADDR(u);
  688. if (targetip.isNull()) {
  689. set_return_addr(hostport,hostname);
  690. targetip.ipset(returnep);
  691. }
  692. socklen_t ul = setSockAddr(u,targetip,hostport);
  693. sock = ::socket(u.sa.sa_family, SOCK_STREAM, targetip.isIp4()?0:PF_INET6);
  694. owned = true;
  695. state = ss_pre_open; // will be set to open by post_connect
  696. if (sock == INVALID_SOCKET) {
  697. int err = ERRNO();
  698. THROWJSOCKEXCEPTION(err);
  699. }
  700. STATS.activesockets++;
  701. int err = 0;
  702. set_nonblock(!block);
  703. int rc = ::connect(sock, &u.sa, ul);
  704. if (rc==SOCKET_ERROR) {
  705. err = ERRNO();
  706. if ((err != EINPROGRESS)&&(err != EWOULDBLOCK)&&(err != ETIMEDOUT)&&(err!=ECONNREFUSED)) { // handled by caller
  707. if (err != ENETUNREACH) {
  708. atomic_set(&pre_conn_unreach_cnt, 0);
  709. LOGERR2(err,1,"pre_connect");
  710. } else {
  711. int ecnt = atomic_read(&pre_conn_unreach_cnt);
  712. if (ecnt <= PRE_CONN_UNREACH_ELIM) {
  713. atomic_inc(&pre_conn_unreach_cnt);
  714. LOGERR2(err,1,"pre_connect network unreachable");
  715. }
  716. }
  717. } else
  718. atomic_set(&pre_conn_unreach_cnt, 0);
  719. } else
  720. atomic_set(&pre_conn_unreach_cnt, 0);
  721. #ifdef SOCKTRACE
  722. PROGLOG("SOCKTRACE: pre-connected socket%s %x %d (%x) err=%d", block?"(block)":"", sock, sock, (int)this, err);
  723. #endif
  724. return err;
  725. }
  726. int CSocket::post_connect ()
  727. {
  728. set_nonblock(false);
  729. int err = 0;
  730. socklen_t errlen = sizeof(err);
  731. int rc = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); // check for error
  732. if ((rc!=0)&&!err)
  733. err = ERRNO(); // some implementations of getsockopt duff
  734. if (err==0) {
  735. nagling = true;
  736. set_nagle(false);
  737. state = ss_open;
  738. }
  739. else if ((err!=ETIMEDOUT)&&(err!=ECONNREFUSED)) // handled by caller
  740. LOGERR2(err,1,"post_connect");
  741. return err;
  742. }
  743. void CSocket::open(int listen_queue_size,bool reuseports)
  744. {
  745. if (IP6preferred)
  746. sock = ::socket(AF_INET6, connectionless()?SOCK_DGRAM:SOCK_STREAM, PF_INET6);
  747. else
  748. sock = ::socket(AF_INET, connectionless()?SOCK_DGRAM:SOCK_STREAM, 0);
  749. if (sock == INVALID_SOCKET) {
  750. THROWJSOCKEXCEPTION(ERRNO());
  751. }
  752. STATS.activesockets++;
  753. #ifdef SOCKTRACE
  754. PROGLOG("SOCKTRACE: opened socket %x %d (%x)", sock,sock,this);
  755. #endif
  756. if ((hostport==0)&&(sockmode==sm_udp)) {
  757. state = ss_open;
  758. #ifdef SOCKTRACE
  759. PROGLOG("SOCKTRACE: opened socket return udp");
  760. #endif
  761. set_inherit(false);
  762. return;
  763. }
  764. #ifndef _WIN32
  765. reuseports = true; // for some reason linux requires reuse ports
  766. #endif
  767. if (reuseports) {
  768. int on = 1;
  769. setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
  770. }
  771. DEFINE_SOCKADDR(u);
  772. socklen_t ul;
  773. if (hostname) {
  774. if (targetip.isNull()) {
  775. set_return_addr(hostport,hostname);
  776. targetip.ipset(returnep);
  777. }
  778. ul = setSockAddr(u,targetip,hostport);
  779. }
  780. else
  781. ul = setSockAddrAny(u,hostport);
  782. int saverr;
  783. if (::bind(sock, &u.sa, ul) != 0) {
  784. saverr = ERRNO();
  785. if (saverr==EADDRINUSE) { // don't log as error (some usages probe ports)
  786. ErrPortInUse:
  787. closesock();
  788. char msg[1024];
  789. sprintf(msg,"Target: %s, port = %d, Raised in: %s, line %d",tracename,(int)hostport,__FILE__, __LINE__);
  790. IJSOCK_Exception *e = new SocketException(JSOCKERR_port_in_use,msg);
  791. throw e;
  792. }
  793. else {
  794. closesock();
  795. THROWJSOCKEXCEPTION(saverr);
  796. }
  797. }
  798. if (!connectionless()) {
  799. if (::listen(sock, listen_queue_size) != 0) {
  800. saverr = ERRNO();
  801. if (saverr==EADDRINUSE)
  802. goto ErrPortInUse;
  803. closesock();
  804. THROWJSOCKEXCEPTION(saverr);
  805. }
  806. }
  807. if (mcastreq) {
  808. if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)mcastreq, sizeof(*mcastreq))!=0) {
  809. saverr = ERRNO();
  810. closesock();
  811. THROWJSOCKEXCEPTION(saverr);
  812. }
  813. }
  814. state = ss_open;
  815. #ifdef SOCKTRACE
  816. PROGLOG("SOCKTRACE: opened socket return");
  817. #endif
  818. set_inherit(false);
  819. }
  820. ISocket* CSocket::accept(bool allowcancel)
  821. {
  822. if ((accept_cancel_state!=accept_not_cancelled) && allowcancel) {
  823. accept_cancel_state=accept_cancelled;
  824. return NULL;
  825. }
  826. if (state != ss_open) {
  827. ERRLOG("invalid accept, state = %d",(int)state);
  828. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  829. }
  830. if (connectionless()) {
  831. THROWJSOCKEXCEPTION(JSOCKERR_connectionless_socket);
  832. }
  833. T_SOCKET newsock;
  834. loop {
  835. in_accept = true;
  836. newsock = (sock!=INVALID_SOCKET)?::accept(sock, NULL, NULL):INVALID_SOCKET;
  837. in_accept = false;
  838. #ifdef SOCKTRACE
  839. PROGLOG("SOCKTRACE: accept created socket %x %d (%x)", newsock,newsock,this);
  840. #endif
  841. if (newsock!=INVALID_SOCKET) {
  842. if ((sock==INVALID_SOCKET)||(accept_cancel_state==accept_cancel_pending)) {
  843. ::close(newsock);
  844. newsock=INVALID_SOCKET;
  845. }
  846. else {
  847. accept_cancel_state = accept_not_cancelled;
  848. break;
  849. }
  850. }
  851. int saverr;
  852. saverr = ERRNO();
  853. if ((sock==INVALID_SOCKET)||(accept_cancel_state==accept_cancel_pending)) {
  854. accept_cancel_state = accept_cancelled;
  855. if (allowcancel)
  856. return NULL;
  857. THROWJSOCKEXCEPTION(JSOCKERR_cancel_accept);
  858. }
  859. if (saverr != EINTRCALL) {
  860. accept_cancel_state = accept_not_cancelled;
  861. THROWJSOCKEXCEPTION(saverr);
  862. }
  863. }
  864. if (state != ss_open) {
  865. accept_cancel_state = accept_cancelled;
  866. if (allowcancel)
  867. return NULL;
  868. THROWJSOCKEXCEPTION(JSOCKERR_cancel_accept);
  869. }
  870. CSocket *ret = new CSocket(newsock,sm_tcp,true);
  871. ret->set_inherit(false);
  872. return ret;
  873. }
  874. void CSocket::set_linger(int lingertime)
  875. {
  876. struct linger l;
  877. l.l_onoff = (lingertime>=0)?1:0;
  878. l.l_linger = (lingertime>=0)?lingertime:0;
  879. if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)) != 0) {
  880. WARNLOG("Linger not set");
  881. }
  882. }
  883. void CSocket::set_keep_alive(bool set)
  884. {
  885. int on=set?1:0;
  886. if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)) != 0) {
  887. WARNLOG("KeepAlive not set");
  888. }
  889. }
  890. int CSocket::name(char *retname,size32_t namemax)
  891. {
  892. if (!retname)
  893. namemax = 0;
  894. if (namemax)
  895. retname[0] = 0;
  896. if (state != ss_open) {
  897. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  898. }
  899. DEFINE_SOCKADDR(u);
  900. socklen_t ul = sizeof(u);
  901. if (::getsockname(sock,&u.sa, &ul)<0) {
  902. THROWJSOCKEXCEPTION(ERRNO());
  903. }
  904. SocketEndpoint ep;
  905. getSockAddrEndpoint(u,ul,ep);
  906. if (namemax>=1)
  907. {
  908. StringBuffer s;
  909. ep.getIpText(s);
  910. if (namemax-1<s.length())
  911. s.setLength(namemax-1);
  912. memcpy(retname,s.str(),s.length()+1);
  913. }
  914. return ep.port;
  915. }
  916. int CSocket::peer_name(char *retname,size32_t namemax)
  917. {
  918. // should not raise exceptions
  919. int ret = 0;
  920. if (!retname)
  921. namemax = 0;
  922. if (namemax)
  923. retname[0] = 0;
  924. if (state != ss_open) {
  925. return -1; // don't log as used to test socket
  926. }
  927. StringBuffer s;
  928. if (sockmode==sm_udp_server) { // udp server
  929. returnep.getIpText(s);
  930. ret = returnep.port;
  931. }
  932. else {
  933. DEFINE_SOCKADDR(u);
  934. socklen_t ul = sizeof(u);
  935. if (::getpeername(sock,&u.sa, &ul)<0)
  936. return -1; // don't log as used to test socket
  937. SocketEndpoint ep;
  938. getSockAddrEndpoint(u,ul,ep);
  939. ep.getIpText(s);
  940. ret = ep.port;
  941. }
  942. if (namemax>1) {
  943. if (namemax-1<s.length())
  944. s.setLength(namemax-1);
  945. memcpy(retname,s.str(),s.length()+1);
  946. }
  947. return ret;
  948. }
  949. SocketEndpoint &CSocket::getPeerEndpoint(SocketEndpoint &ep)
  950. {
  951. if (state != ss_open) {
  952. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  953. }
  954. StringBuffer s;
  955. if (sockmode==sm_udp_server) { // udp server
  956. ep.set(returnep);
  957. }
  958. else {
  959. DEFINE_SOCKADDR(u);
  960. socklen_t ul = sizeof(u);
  961. if (::getpeername(sock,&u.sa, &ul)<0) {
  962. DBGLOG("getpeername failed %d",ERRNO());
  963. ep.set(NULL, 0);
  964. }
  965. else
  966. getSockAddrEndpoint(u,ul,ep);
  967. }
  968. return ep;
  969. }
  970. IpAddress & CSocket::getPeerAddress(IpAddress &addr)
  971. {
  972. SocketEndpoint ep;
  973. getPeerEndpoint(ep);
  974. addr = ep;
  975. return addr;
  976. }
  977. void CSocket::set_return_addr(int port,const char *retname)
  978. {
  979. if (!returnep.ipset(retname)) {
  980. IJSOCK_Exception *e = new SocketException(JSOCKERR_bad_address); // don't use THROWJSOCKEXCEPTION here
  981. throw e;
  982. }
  983. returnep.port = port;
  984. }
  985. void CSocket::cancel_accept()
  986. {
  987. if (connectionless()) {
  988. THROWJSOCKEXCEPTION(JSOCKERR_connectionless_socket);
  989. }
  990. #ifdef SOCKTRACE
  991. PROGLOG("SOCKTRACE: Cancel accept socket %x %d (%x)", sock, sock, this);
  992. #endif
  993. if (!in_accept) {
  994. accept_cancel_state = accept_cancelled;
  995. errclose();
  996. return;
  997. }
  998. accept_cancel_state = accept_cancel_pending;
  999. errclose(); // this should cause accept to terminate (not supported on all linux though)
  1000. #ifdef _WIN32
  1001. for (unsigned i=0;i<5;i++) { // windows closes on different lower priority thread
  1002. Sleep(i);
  1003. if (accept_cancel_state==accept_cancelled)
  1004. return;
  1005. }
  1006. #else
  1007. Sleep(0);
  1008. if (accept_cancel_state==accept_cancelled)
  1009. return;
  1010. #endif
  1011. // Wakeup listener using a connection
  1012. SocketEndpoint ep(hostport,queryHostIP());
  1013. Owned<CSocket> sock = new CSocket(ep,sm_tcp,NULL);
  1014. try {
  1015. sock->connect_timeout(100,true);
  1016. }
  1017. catch (IJSOCK_Exception *e) {
  1018. EXCLOG(e,"CSocket::cancel_eccept");
  1019. e->Release();
  1020. }
  1021. }
  1022. // ================================================================================
  1023. // connect versions
  1024. ISocket* ISocket::connect( const SocketEndpoint &ep )
  1025. {
  1026. // general connect
  1027. return ISocket::connect_wait(ep,DEFAULT_CONNECT_TIME);
  1028. }
  1029. inline void refused_sleep(CTimeMon &tm, unsigned &refuseddelay)
  1030. {
  1031. unsigned remaining;
  1032. if (!tm.timedout(&remaining)) {
  1033. if (refuseddelay<remaining/4) {
  1034. Sleep(refuseddelay);
  1035. if (refuseddelay<CONNECT_TIMEOUT_REFUSED_WAIT/2)
  1036. refuseddelay *=2;
  1037. else
  1038. refuseddelay = CONNECT_TIMEOUT_REFUSED_WAIT;
  1039. }
  1040. else
  1041. Sleep(remaining/4); // towards end of timeout approach gradually
  1042. }
  1043. }
  1044. bool CSocket::connect_timeout( unsigned timeout, bool noexception)
  1045. {
  1046. // simple connect with timeout (no fancy stuff!)
  1047. unsigned startt = usTick();
  1048. CTimeMon tm(timeout);
  1049. unsigned remaining;
  1050. unsigned refuseddelay = 1;
  1051. int err;
  1052. while (!tm.timedout(&remaining)) {
  1053. err = pre_connect(false);
  1054. if ((err == EINPROGRESS)||(err == EWOULDBLOCK)) {
  1055. T_FD_SET fds;
  1056. struct timeval tv;
  1057. XFD_ZERO(&fds);
  1058. FD_SET((unsigned)sock, &fds);
  1059. T_FD_SET except;
  1060. XFD_ZERO(&except);
  1061. FD_SET((unsigned)sock, &except);
  1062. tv.tv_sec = remaining / 1000;
  1063. tv.tv_usec = (remaining % 1000)*1000;
  1064. CHECKSOCKRANGE(sock);
  1065. int rc = ::select( sock + 1, NULL, (fd_set *)&fds, (fd_set *)&except, &tv );
  1066. if (rc>0) {
  1067. // select succeeded - return error from socket (0 if connected)
  1068. socklen_t errlen = sizeof(err);
  1069. rc = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); // check for error
  1070. if ((rc!=0)&&!err)
  1071. err = ERRNO(); // some implementations of getsockopt duff
  1072. if (err) // probably ECONNREFUSED but treat all errors same
  1073. refused_sleep(tm,refuseddelay);
  1074. }
  1075. else if (rc<0) {
  1076. err = ERRNO();
  1077. LOGERR2(err,2,"::select");
  1078. }
  1079. }
  1080. if (err==0) {
  1081. err = post_connect();
  1082. if (err==0) {
  1083. STATS.connects++;
  1084. STATS.connecttime+=usTick()-startt;
  1085. #ifdef _TRACE
  1086. char peer[256];
  1087. peer[0] = 'C';
  1088. peer[1] = '!';
  1089. strcpy(peer+2,hostname?hostname:"(NULL)");
  1090. free(tracename);
  1091. tracename = strdup(peer);
  1092. #endif
  1093. return true;
  1094. }
  1095. }
  1096. errclose();
  1097. }
  1098. #ifdef SOCKTRACE
  1099. PROGLOG("connect_timeout: failed %d",err);
  1100. #endif
  1101. STATS.failedconnects++;
  1102. STATS.failedconnecttime+=usTick()-startt;
  1103. if (!noexception)
  1104. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  1105. return false;
  1106. }
  1107. ISocket* ISocket::connect_timeout(const SocketEndpoint &ep,unsigned timeout)
  1108. {
  1109. if (ep.isNull()||(ep.port==0))
  1110. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  1111. Owned<CSocket> sock = new CSocket(ep,sm_tcp,NULL);
  1112. sock->connect_timeout(timeout,false);
  1113. return sock.getClear();
  1114. }
  1115. #define POLLTIME 50
  1116. void CSocket::connect_wait(unsigned timems)
  1117. {
  1118. // simple connect with timeout (no fancy stuff!)
  1119. unsigned startt = usTick();
  1120. CTimeMon tm(timems);
  1121. bool exit = false;
  1122. int err;
  1123. unsigned refuseddelay = 1;
  1124. while (!exit) {
  1125. #ifdef CENTRAL_NODE_RANDOM_DELAY
  1126. ForEachItemIn(cn,CentralNodeArray) {
  1127. SocketEndpoint &ep=CentralNodeArray.item(cn);
  1128. if (ep.ipequals(targetip)) {
  1129. unsigned sleeptime = getRandom() % 1000;
  1130. StringBuffer s;
  1131. ep.getIpText(s);
  1132. PrintLog("Connection to central node %s - sleeping %d milliseconds", s.str(), sleeptime);
  1133. Sleep(sleeptime);
  1134. break;
  1135. }
  1136. }
  1137. #endif
  1138. unsigned remaining;
  1139. exit = tm.timedout(&remaining);
  1140. bool blockselect = exit; // if last time round block
  1141. {
  1142. CriticalBlock block(crit);
  1143. if (++connectingcount>4)
  1144. blockselect = true;
  1145. }
  1146. err = pre_connect(blockselect);
  1147. if (blockselect) {
  1148. if (err&&!exit)
  1149. refused_sleep(tm,refuseddelay); // probably ECONNREFUSED but treat all errors same
  1150. }
  1151. else {
  1152. unsigned timeoutms = (exit||(remaining<10000))?10000:remaining;
  1153. unsigned polltime = 1;
  1154. while (!blockselect && ((err == EINPROGRESS)||(err == EWOULDBLOCK))) {
  1155. T_FD_SET fds;
  1156. struct timeval tv;
  1157. XFD_ZERO(&fds);
  1158. FD_SET((unsigned)sock, &fds);
  1159. T_FD_SET except;
  1160. XFD_ZERO(&except);
  1161. FD_SET((unsigned)sock, &except);
  1162. #ifdef BLOCK_POLLED_SINGLE_CONNECTS
  1163. tv.tv_sec = timeoutms / 1000;
  1164. tv.tv_usec = (timeoutms % 1000)*1000;
  1165. #else
  1166. tv.tv_sec = 0;
  1167. tv.tv_usec = 0;
  1168. #endif
  1169. CHECKSOCKRANGE(sock);
  1170. int rc = ::select( sock + 1, NULL, (fd_set *)&fds, (fd_set *)&except, &tv );
  1171. if (rc>0) {
  1172. // select succeeded - return error from socket (0 if connected)
  1173. socklen_t errlen = sizeof(err);
  1174. rc = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); // check for error
  1175. if ((rc!=0)&&!err)
  1176. err = ERRNO(); // some implementations of getsockopt duff
  1177. if (err)
  1178. refused_sleep(tm,refuseddelay); // probably ECONNREFUSED but treat all errors same
  1179. break;
  1180. }
  1181. if (rc<0) {
  1182. err = ERRNO();
  1183. LOGERR2(err,2,"::select");
  1184. break;
  1185. }
  1186. if (!timeoutms) {
  1187. #ifdef SOCKTRACE
  1188. PROGLOG("connecttimeout: timed out");
  1189. #endif
  1190. err = -1;
  1191. break;
  1192. }
  1193. #ifdef BLOCK_POLLED_SINGLE_CONNECTS
  1194. break;
  1195. #else
  1196. if (timeoutms<polltime)
  1197. polltime = timeoutms;
  1198. Sleep(polltime); // sleeps 1-50ms (to let other threads run)
  1199. timeoutms -= polltime;
  1200. if (polltime>POLLTIME/2)
  1201. polltime = POLLTIME;
  1202. else
  1203. polltime *= 2;
  1204. #endif
  1205. }
  1206. }
  1207. {
  1208. CriticalBlock block(crit);
  1209. --connectingcount;
  1210. }
  1211. if (err==0) {
  1212. err = post_connect();
  1213. if (err==0) {
  1214. STATS.connects++;
  1215. STATS.connecttime+=usTick()-startt;
  1216. #ifdef _TRACE
  1217. char peer[256];
  1218. peer[0] = 'C';
  1219. peer[1] = '!';
  1220. strcpy(peer+2,hostname?hostname:"(NULL)");
  1221. free(tracename);
  1222. tracename = strdup(peer);
  1223. #endif
  1224. return;
  1225. }
  1226. }
  1227. errclose();
  1228. }
  1229. #ifdef SOCKTRACE
  1230. PROGLOG("connect_wait: failed %d",err);
  1231. #endif
  1232. STATS.failedconnects++;
  1233. STATS.failedconnecttime+=usTick()-startt;
  1234. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  1235. }
  1236. ISocket* ISocket::connect_wait( const SocketEndpoint &ep, unsigned timems)
  1237. {
  1238. if (ep.isNull()||(ep.port==0))
  1239. THROWJSOCKEXCEPTION2(JSOCKERR_bad_address);
  1240. Owned<CSocket> sock = new CSocket(ep,sm_tcp,NULL);
  1241. sock->connect_wait(timems);
  1242. return sock.getClear();
  1243. }
  1244. void CSocket::udpconnect()
  1245. {
  1246. DEFINE_SOCKADDR(u);
  1247. if (targetip.isNull()) {
  1248. set_return_addr(hostport,hostname);
  1249. targetip.ipset(returnep);
  1250. }
  1251. socklen_t ul = setSockAddr(u,targetip,hostport);
  1252. sock = ::socket(u.sa.sa_family, SOCK_DGRAM, targetip.isIp4()?0:PF_INET6);
  1253. #ifdef SOCKTRACE
  1254. PROGLOG("SOCKTRACE: udp connected socket %x %d (%x)", sock, sock, this);
  1255. #endif
  1256. STATS.activesockets++;
  1257. if (sock == INVALID_SOCKET) {
  1258. THROWJSOCKEXCEPTION(ERRNO());
  1259. }
  1260. int res = ::connect(sock, &u.sa, ul);
  1261. if (res != 0) { // works for UDP
  1262. closesock();
  1263. THROWJSOCKEXCEPTION(JSOCKERR_connection_failed);
  1264. }
  1265. nagling = false; // means nothing for UDP
  1266. state = ss_open;
  1267. #ifdef _TRACE
  1268. char peer[256];
  1269. peer[0] = 'C';
  1270. peer[1] = '!';
  1271. strcpy(peer+2,hostname?hostname:"(NULL)");
  1272. free(tracename);
  1273. tracename = strdup(peer);
  1274. #endif
  1275. }
  1276. int CSocket::wait_read(unsigned timeout)
  1277. {
  1278. int ret = 0;
  1279. while (sock!=INVALID_SOCKET) {
  1280. T_FD_SET fds;
  1281. XFD_ZERO(&fds);
  1282. FD_SET((unsigned)sock, &fds);
  1283. CHECKSOCKRANGE(sock);
  1284. if (timeout==WAIT_FOREVER) {
  1285. ret = ::select( sock + 1, (fd_set *)&fds, NULL, NULL, NULL );
  1286. }
  1287. else {
  1288. struct timeval tv;
  1289. tv.tv_sec = timeout / 1000;
  1290. tv.tv_usec = (timeout % 1000)*1000;
  1291. ret = ::select( sock + 1, (fd_set *)&fds, NULL, NULL, &tv );
  1292. }
  1293. if (ret==SOCKET_ERROR) {
  1294. int err = ERRNO();
  1295. if (err!=EINTRCALL) { // else retry (should adjust time but for our usage don't think it matters that much)
  1296. LOGERR2(err,1,"wait_read");
  1297. break;
  1298. }
  1299. }
  1300. else
  1301. break;
  1302. }
  1303. return ret;
  1304. }
  1305. int CSocket::wait_write(unsigned timeout)
  1306. {
  1307. int ret = 0;
  1308. while (sock!=INVALID_SOCKET) {
  1309. T_FD_SET fds;
  1310. XFD_ZERO(&fds);
  1311. FD_SET((unsigned)sock, &fds);
  1312. CHECKSOCKRANGE(sock);
  1313. if (timeout==WAIT_FOREVER) {
  1314. ret = ::select( sock + 1, NULL, (fd_set *)&fds, NULL, NULL );
  1315. }
  1316. else {
  1317. struct timeval tv;
  1318. tv.tv_sec = timeout / 1000;
  1319. tv.tv_usec = (timeout % 1000)*1000;
  1320. ret = ::select( sock + 1, NULL, (fd_set *)&fds, NULL, &tv );
  1321. }
  1322. if (ret==SOCKET_ERROR) {
  1323. int err = ERRNO();
  1324. if (err!=EINTRCALL) { // else retry (should adjust time but for our usage don't think it matters that much)
  1325. LOGERR2(err,1,"wait_write");
  1326. break;
  1327. }
  1328. }
  1329. else
  1330. break;
  1331. }
  1332. return ret;
  1333. }
  1334. void CSocket::readtms(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read,
  1335. unsigned timeoutms)
  1336. {
  1337. if (timeoutms == WAIT_FOREVER) {
  1338. read(buf,min_size, max_size, size_read,WAIT_FOREVER);
  1339. return;
  1340. }
  1341. unsigned startt=usTick();
  1342. size_read = 0;
  1343. if (state != ss_open) {
  1344. THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
  1345. }
  1346. unsigned start;
  1347. unsigned timeleft;
  1348. start = msTick();
  1349. timeleft = timeoutms;
  1350. do {
  1351. int rc = wait_read(timeleft);
  1352. if (rc < 0) {
  1353. THROWJSOCKEXCEPTION(ERRNO());
  1354. }
  1355. if (rc == 0) {
  1356. THROWJSOCKEXCEPTION(JSOCKERR_timeout_expired);
  1357. }
  1358. unsigned elapsed = (msTick()-start);
  1359. if (elapsed<timeoutms)
  1360. timeleft = timeoutms-elapsed;
  1361. else
  1362. timeleft = 0;
  1363. unsigned retrycount=100;
  1364. EintrRetry:
  1365. if (sockmode==sm_udp_server) { // udp server
  1366. DEFINE_SOCKADDR(u);
  1367. socklen_t ul=sizeof(u);
  1368. rc = recvfrom(sock, (char*)buf + size_read, max_size - size_read, 0, &u.sa,&ul);
  1369. getSockAddrEndpoint(u,ul,returnep);
  1370. }
  1371. else {
  1372. rc = recv(sock, (char*)buf + size_read, max_size - size_read, 0);
  1373. }
  1374. if (rc < 0) {
  1375. int err = ERRNO();
  1376. if (BADSOCKERR(err)) {
  1377. // don't think this should happen but convert to same as shutdown while investigation
  1378. LOGERR2(err,1,"Soc…

Large files files are truncated, but you can click here to view the full file