7777#include < unistd.h>
7878#endif
7979
80+ #ifdef HAVE_SYS_TIME_H
81+ #include < sys/time.h>
82+ #endif
8083
8184
8285#ifdef WIN_NT
@@ -632,6 +635,7 @@ static rem_port* inet_try_connect( PACKET*,
632635 const PathName&,
633636 const TEXT *,
634637 ClumpletReader&,
638+ const ParametersSet*,
635639 RefPtr<const Config>*,
636640 const PathName*,
637641 int );
@@ -657,7 +661,7 @@ static int send_partial(rem_port*, PACKET *);
657661
658662static RemoteXdr* xdrinet_create (rem_port*, UCHAR *, USHORT , enum xdr_op);
659663static bool setNoNagleOption (rem_port*);
660- static bool setKeepAlive (SOCKET );
664+ static bool setKeepAlive (SOCKET , rem_port* = nullptr );
661665static FPTR_INT tryStopMainThread = 0 ;
662666
663667
@@ -797,6 +801,7 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
797801 const TEXT * node_name,
798802 bool uv_flag,
799803 ClumpletReader &dpb,
804+ const ParametersSet* par,
800805 RefPtr<const Config>* config,
801806 const PathName* ref_db_name,
802807 ICryptKeyCallback* cryptCb,
@@ -900,7 +905,7 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
900905 }
901906 }
902907
903- rem_port* port = inet_try_connect (packet, rdb, file_name, node_name, dpb, config, ref_db_name, af);
908+ rem_port* port = inet_try_connect (packet, rdb, file_name, node_name, dpb, par, config, ref_db_name, af);
904909 P_ACPT * accept;
905910
906911 for (;;)
@@ -1032,6 +1037,7 @@ rem_port* INET_connect(const TEXT* name,
10321037 PACKET * packet,
10331038 USHORT flag,
10341039 ClumpletReader* dpb,
1040+ const ParametersSet* par,
10351041 RefPtr<const Config>* config,
10361042 int af,
10371043 bool disableTcp)
@@ -1069,7 +1075,7 @@ rem_port* INET_connect(const TEXT* name,
10691075 {
10701076 port->port_config = *config;
10711077 }
1072- REMOTE_get_timeout_params (port, dpb);
1078+ REMOTE_get_timeout_params (port, dpb, par );
10731079
10741080 const RefPtr<const Config> portConfig = port->getPortConfig ();
10751081 const bool explicitTcpPort = !packet && name && name[0 ];
@@ -1225,7 +1231,7 @@ rem_port* INET_connect(const TEXT* name,
12251231 return listener_socket (port, flag, pai);
12261232
12271233 // client
1228- if (!setKeepAlive (port->port_handle ))
1234+ if (!setKeepAlive (port->port_handle , port ))
12291235 gds__log (" setsockopt: error setting SO_KEEPALIVE" );
12301236
12311237 if (!setNoNagleOption (port))
@@ -1553,7 +1559,7 @@ static rem_port* listener_socket(rem_port* port, USHORT flag, const addrinfo* pa
15531559 }
15541560 else
15551561 {
1556- if (! setKeepAlive (port->port_handle ))
1562+ if (! setKeepAlive (port->port_handle , port ))
15571563 {
15581564 inet_error (true , port, " setsockopt SO_KEEPALIVE" , isc_net_connect_listen_err, INET_ERRNO );
15591565 }
@@ -1701,7 +1707,7 @@ rem_port* INET_reconnect(SOCKET handle, bool unixSocket)
17011707 else
17021708#endif
17031709 {
1704- if (! setKeepAlive (port->port_handle )) {
1710+ if (! setKeepAlive (port->port_handle , port )) {
17051711 gds__log (" inet server err: setting KEEPALIVE socket option \n " );
17061712 }
17071713
@@ -1731,7 +1737,7 @@ rem_port* INET_server(SOCKET sock)
17311737 port->port_server_flags |= SRVR_server;
17321738 port->port_handle = sock;
17331739
1734- if (! setKeepAlive (port->port_handle )) {
1740+ if (! setKeepAlive (port->port_handle , port )) {
17351741 gds__log (" inet server err: setting KEEPALIVE socket option \n " );
17361742 }
17371743
@@ -1870,7 +1876,7 @@ static rem_port* alloc_port(rem_port* const parent, const USHORT flags)
18701876 }
18711877
18721878 rem_port* const port = FB_NEW rem_port (rem_port::INET , INET_remote_buffer * 2 );
1873- REMOTE_get_timeout_params (port, 0 );
1879+ REMOTE_get_timeout_params (port, nullptr , nullptr );
18741880
18751881 TEXT buffer[BUFFER_SMALL ];
18761882 gethostname (buffer, sizeof (buffer));
@@ -3397,6 +3403,7 @@ static rem_port* inet_try_connect(PACKET* packet,
33973403 const PathName& file_name,
33983404 const TEXT * node_name,
33993405 ClumpletReader& dpb,
3406+ const ParametersSet* par,
34003407 RefPtr<const Config>* config,
34013408 const PathName* ref_db_name,
34023409 int af)
@@ -3431,7 +3438,7 @@ static rem_port* inet_try_connect(PACKET* packet,
34313438 rem_port* port = NULL ;
34323439 try
34333440 {
3434- port = INET_connect (node_name, packet, false , &dpb, config, af);
3441+ port = INET_connect (node_name, packet, false , &dpb, par, config, af);
34353442 }
34363443 catch (const Exception&)
34373444 {
@@ -3534,21 +3541,26 @@ static bool packet_receive(rem_port* port, UCHAR* buffer, SSHORT buffer_length,
35343541 }
35353542
35363543 timeval timeout{};
3537- timeval* time_ptr = NULL ;
3544+ timeval* time_ptr = &timeout ;
35383545
3539- if (port->port_protocol == 0 )
3546+ if (port->port_protocol == 0 && port-> port_connect_timeout )
35403547 {
35413548 // If the protocol is 0 we are still in the process of establishing
35423549 // a connection. Add a time out to the wait.
35433550 timeout.tv_sec = port->port_connect_timeout ;
3544- time_ptr = &timeout;
3551+ }
3552+ else if (port->port_receive_timeout )
3553+ {
3554+ // Should stop waiting and report error
3555+ timeout.tv_sec = port->port_receive_timeout ;
35453556 }
35463557 else if (port->port_dummy_packet_interval > 0 )
35473558 {
35483559 // Set the time interval for sending dummy packets to the client
35493560 timeout.tv_sec = port->port_dummy_packet_interval ;
3550- time_ptr = &timeout;
35513561 }
3562+ else
3563+ time_ptr = nullptr ;
35523564
35533565 // On Linux systems (and possibly others too) select will eventually
35543566 // change timout values so save it here for later reuse.
@@ -3623,7 +3635,7 @@ static bool packet_receive(rem_port* port, UCHAR* buffer, SSHORT buffer_length,
36233635
36243636 if (!slct_count)
36253637 {
3626- if (port->port_protocol == 0 )
3638+ if (port->port_protocol == 0 || port-> port_receive_timeout )
36273639 return false ;
36283640
36293641#ifdef DEBUG
@@ -3905,7 +3917,19 @@ static bool setNoNagleOption(rem_port* port)
39053917 return true ;
39063918}
39073919
3908- static bool setKeepAlive (SOCKET s)
3920+ static bool setTimeout (SOCKET s, int timeout, int optname)
3921+ {
3922+ #ifdef WIN_NT
3923+ DWORD tv = timeout * 1000 ;
3924+ #else
3925+ struct timeval tv;
3926+ tv.tv_sec = timeout;
3927+ tv.tv_usec = 0 ;
3928+ #endif
3929+ return setsockopt (s, SOL_SOCKET , optname, &tv, sizeof (tv)) >= 0 ;
3930+ }
3931+
3932+ static bool setKeepAlive (SOCKET s, rem_port* port)
39093933{
39103934/* *************************************
39113935 *
@@ -3914,14 +3938,32 @@ static bool setKeepAlive(SOCKET s)
39143938 **************************************
39153939 *
39163940 * Functional description
3917- * Set SO_KEEPALIVE, return false
3918- * in case of unexpected error
3941+ * Set SO_KEEPALIVE, SO_SNDTIMEO & SO_RCVTIMEO,
3942+ * return false in case of unexpected error.
39193943 *
39203944 **************************************/
39213945 constexpr int optval = 1 ;
39223946 const int n = setsockopt (s, SOL_SOCKET , SO_KEEPALIVE ,
39233947 (SCHAR *) &optval, sizeof (optval));
3924- return n != -1 ;
3948+ if (n < 0 )
3949+ return false ;
3950+
3951+ if (port)
3952+ {
3953+ if (port->port_send_timeout )
3954+ {
3955+ if (!setTimeout (s, port->port_send_timeout , SO_SNDTIMEO ))
3956+ return false ;
3957+ }
3958+
3959+ if (port->port_receive_timeout )
3960+ {
3961+ if (!setTimeout (s, port->port_receive_timeout , SO_RCVTIMEO ))
3962+ return false ;
3963+ }
3964+ }
3965+
3966+ return true ;
39253967}
39263968
39273969void setStopMainThread (FPTR_INT func)
0 commit comments