@@ -253,12 +253,45 @@ constexpr ULONG DEF_MAX_DATA = 8192;
253253
254254constexpr int SELECT_TIMEOUT = 60 ; // Dispatch thread select timeout (sec)
255255
256+ class ForRead
257+ {
258+ public:
259+ static constexpr int SEL_INIT_EVENTS = POLLIN ;
260+ static constexpr int SEL_CHECK_MASK = POLLIN ;
261+
262+ static fd_set* readSet (fd_set* set)
263+ {
264+ return set;
265+ }
266+
267+ static fd_set* writeSet (fd_set* set)
268+ {
269+ return nullptr ;
270+ }
271+ };
272+
273+ class ForWrite
274+ {
275+ public:
276+ static constexpr int SEL_INIT_EVENTS = POLLOUT ;
277+ static constexpr int SEL_CHECK_MASK = POLLOUT ;
278+
279+ static fd_set* readSet (fd_set* set)
280+ {
281+ return nullptr ;
282+ }
283+
284+ static fd_set* writeSet (fd_set* set)
285+ {
286+ return set;
287+ }
288+ };
289+
290+ template <class Traits >
256291class Select
257292{
258293#ifdef HAVE_POLL
259294private:
260- static constexpr int SEL_INIT_EVENTS = POLLIN ;
261- static constexpr int SEL_CHECK_MASK = POLLIN ;
262295
263296 pollfd* getPollFd (int n)
264297 {
@@ -377,7 +410,7 @@ class Select
377410
378411 if (pf)
379412 {
380- HandleState ret = pf->events & SEL_CHECK_MASK ? SEL_READY : SEL_NO_DATA ;
413+ HandleState ret = pf->events & Traits:: SEL_CHECK_MASK ? SEL_READY : SEL_NO_DATA ;
381414 pf->events = 0 ; // unset
382415 return ret;
383416 }
@@ -416,13 +449,13 @@ class Select
416449 FB_SIZE_T pos;
417450 if (slct_poll.find (handle, pos))
418451 {
419- slct_poll[pos].events = SEL_INIT_EVENTS ;
452+ slct_poll[pos].events = Traits:: SEL_INIT_EVENTS ;
420453 }
421454 else
422455 {
423456 pollfd f;
424457 f.fd = handle;
425- f.events = SEL_INIT_EVENTS ;
458+ f.events = Traits:: SEL_INIT_EVENTS ;
426459 slct_poll.insert (pos, f);
427460 }
428461#else
@@ -460,7 +493,7 @@ class Select
460493 for (pollfd* pf = slct_poll.begin (); pf < end; ++pf)
461494 {
462495 pf->revents = pf->events ;
463- if (pf->events & SEL_CHECK_MASK )
496+ if (pf->events & Traits:: SEL_CHECK_MASK )
464497 hasRequest = true ;
465498 }
466499
@@ -479,15 +512,15 @@ class Select
479512 for (pollfd* pf = slct_poll.begin (); pf < end; ++pf)
480513 {
481514 pf->events = pf->revents ;
482- if (pf->revents & SEL_CHECK_MASK )
515+ if (pf->revents & Traits:: SEL_CHECK_MASK )
483516 slct_ready.add (pf);
484517 }
485518 }
486519#else
487520#ifdef WIN_NT
488- slct_count = ::select (FD_SETSIZE , &slct_fdset, NULL , NULL , timeout);
521+ slct_count = ::select (FD_SETSIZE , readSet ( &slct_fdset), writeSet (&slct_fdset) , NULL , timeout);
489522#else
490- slct_count = ::select (slct_width, &slct_fdset, NULL , NULL , timeout);
523+ slct_count = ::select (slct_width, readSet ( &slct_fdset), writeSet (&slct_fdset) , NULL , timeout);
491524#endif // WIN_NT
492525#endif // HAVE_POLL
493526 }
@@ -616,9 +649,9 @@ static rem_port* receive(rem_port*, PACKET *);
616649static rem_port* select_accept (rem_port*);
617650static bool is_listener (const rem_port*);
618651
619- static void select_port (rem_port*, Select*, RemPortPtr&);
652+ static void select_port (rem_port*, Select<ForRead> *, RemPortPtr&);
620653static bool select_multi (rem_port*, UCHAR * buffer, SSHORT bufsize, SSHORT * length, RemPortPtr&);
621- static bool select_wait (rem_port*, Select*);
654+ static bool select_wait (rem_port*, Select<ForRead> *);
622655static int send_full (rem_port*, PACKET *);
623656static int send_partial (rem_port*, PACKET *);
624657
@@ -667,7 +700,7 @@ ULONG INET_remote_buffer;
667700static GlobalPtr<Mutex> init_mutex;
668701static volatile bool INET_initialized = false ;
669702static volatile bool INET_shutting_down = false ;
670- static GlobalPtr<Select> INET_select;
703+ static GlobalPtr<Select<ForRead> > INET_select;
671704static rem_port* inet_async_receive = NULL ;
672705
673706
@@ -1199,13 +1232,63 @@ rem_port* INET_connect(const TEXT* name,
11991232 gds__log (" setsockopt: error setting TCP_NODELAY" );
12001233 else
12011234 {
1235+ int flags;
1236+ if (port->port_connect_timeout )
1237+ {
1238+ flags = fcntl (port->port_handle , F_GETFL , 0 );
1239+ if (flags < 0 )
1240+ {
1241+ SOCLOSE (port->port_handle );
1242+ continue ;
1243+ }
1244+
1245+ if (fcntl (port->port_handle , F_SETFL , flags | O_NONBLOCK ) < 0 )
1246+ {
1247+ SOCLOSE (port->port_handle );
1248+ continue ;
1249+ }
1250+ }
1251+
12021252 n = connect (port->port_handle , pai->ai_addr , static_cast <socklen_t >(pai->ai_addrlen ));
1203- if (n != -1 )
1253+ if (n != -1 || errno == EINPROGRESS )
12041254 {
1205- port->port_peer_name = host;
1206- get_peer_info (port);
1207- if (send_full (port, packet))
1208- return port;
1255+ bool connected = true ;
1256+ if (n == -1 && errno == EINPROGRESS )
1257+ {
1258+ fb_assert (port->port_connect_timeout );
1259+
1260+ timeval timeout {};
1261+ timeout.tv_sec = port->port_connect_timeout ;
1262+
1263+ Select<ForWrite> slct;
1264+ slct.set (port->port_handle );
1265+ slct.select (&timeout);
1266+ connected = (slct.getCount () > 0 );
1267+
1268+ if (connected)
1269+ {
1270+ int optError;
1271+ socklen_t len = sizeof (optError);
1272+ if (getsockopt (port->port_handle , SOL_SOCKET , SO_ERROR , &optError, &len) < 0 )
1273+ connected = false ;
1274+ else
1275+ connected = (optError == 0 );
1276+ }
1277+
1278+ if (connected)
1279+ {
1280+ if (fcntl (port->port_handle , F_SETFL , flags) < 0 )
1281+ connected = false ;
1282+ }
1283+ }
1284+
1285+ if (connected)
1286+ {
1287+ port->port_peer_name = host;
1288+ get_peer_info (port);
1289+ if (send_full (port, packet))
1290+ return port;
1291+ }
12091292 }
12101293 }
12111294
@@ -1838,7 +1921,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet)
18381921 timeval timeout {};
18391922 timeout.tv_sec = port->port_connect_timeout ;
18401923
1841- Select slct;
1924+ Select<ForRead> slct;
18421925 slct.set (port->port_channel );
18431926
18441927 int inetErrNo = 0 ;
@@ -2649,7 +2732,7 @@ static rem_port* select_accept( rem_port* main_port)
26492732 return 0 ;
26502733}
26512734
2652- static void select_port (rem_port* main_port, Select* selct, RemPortPtr& port)
2735+ static void select_port (rem_port* main_port, Select<ForRead> * selct, RemPortPtr& port)
26532736{
26542737/* *************************************
26552738 *
@@ -2670,23 +2753,23 @@ static void select_port(rem_port* main_port, Select* selct, RemPortPtr& port)
26702753 MutexLockGuard guard (port_mutex, FB_FUNCTION );
26712754 while (true )
26722755 {
2673- const Select::HandleState result = selct->checkNext (port);
2756+ const Select<ForRead> ::HandleState result = selct->checkNext (port);
26742757 if (!port)
26752758 return ;
26762759
26772760 switch (result)
26782761 {
2679- case Select::SEL_BAD :
2762+ case Select<ForRead> ::SEL_BAD :
26802763 if (port->port_state == rem_port::BROKEN || (port->port_flags & PORT_connecting))
26812764 continue ;
26822765 if (port->port_flags & PORT_async)
26832766 continue ;
26842767 return ;
26852768
2686- case Select::SEL_DISCONNECTED :
2769+ case Select<ForRead> ::SEL_DISCONNECTED :
26872770 continue ;
26882771
2689- case Select::SEL_READY :
2772+ case Select<ForRead> ::SEL_READY :
26902773 port->port_dummy_timeout = port->port_dummy_packet_interval ;
26912774 return ;
26922775
@@ -2699,7 +2782,7 @@ static void select_port(rem_port* main_port, Select* selct, RemPortPtr& port)
26992782 }
27002783}
27012784
2702- static bool select_wait ( rem_port* main_port, Select* selct)
2785+ static bool select_wait ( rem_port* main_port, Select<ForRead> * selct)
27032786{
27042787/* *************************************
27052788 *
@@ -3487,7 +3570,7 @@ static bool packet_receive(rem_port* port, UCHAR* buffer, SSHORT buffer_length,
34873570
34883571 if ( !(port->port_flags & PORT_async) )
34893572 {
3490- Select slct;
3573+ Select<ForRead> slct;
34913574 slct.set (ph);
34923575
34933576 int slct_count;
0 commit comments