3030 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
3131 * Portions Copyright (c) 1994, Regents of the University of California
3232 *
33- * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.210 2010/07/06 21:14:25 rhaas Exp $
33+ * $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.211 2010/07/08 10:20:12 mha Exp $
3434 *
3535 *-------------------------------------------------------------------------
3636 */
8383#ifdef HAVE_UTIME_H
8484#include <utime.h>
8585#endif
86+ #ifdef WIN32
87+ #include <mstcpip.h>
88+ #endif
8689
8790#include "libpq/ip.h"
8891#include "libpq/libpq.h"
@@ -1314,10 +1317,55 @@ pq_endcopyout(bool errorAbort)
13141317 * Support for TCP Keepalive parameters
13151318 */
13161319
1320+ /*
1321+ * On Windows, we need to set both idle and interval at the same time.
1322+ * We also cannot reset them to the default (setting to zero will
1323+ * actually set them to zero, not default), therefor we fallback to
1324+ * the out-of-the-box default instead.
1325+ */
1326+ #ifdef WIN32
1327+ static int
1328+ pq_setkeepaliveswin32 (Port * port , int idle , int interval )
1329+ {
1330+ struct tcp_keepalive ka ;
1331+ DWORD retsize ;
1332+
1333+ if (idle <= 0 )
1334+ idle = 2 * 60 * 60 ; /* default = 2 hours */
1335+ if (interval <= 0 )
1336+ interval = 1 ; /* default = 1 second */
1337+
1338+ ka .onoff = 1 ;
1339+ ka .keepalivetime = idle * 1000 ;
1340+ ka .keepaliveinterval = interval * 1000 ;
1341+
1342+ if (WSAIoctl (port -> sock ,
1343+ SIO_KEEPALIVE_VALS ,
1344+ (LPVOID ) & ka ,
1345+ sizeof (ka ),
1346+ NULL ,
1347+ 0 ,
1348+ & retsize ,
1349+ NULL ,
1350+ NULL )
1351+ != 0 )
1352+ {
1353+ elog (LOG , "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui" ,
1354+ WSAGetLastError ());
1355+ return STATUS_ERROR ;
1356+ }
1357+ if (port -> keepalives_idle != idle )
1358+ port -> keepalives_idle = idle ;
1359+ if (port -> keepalives_interval != interval )
1360+ port -> keepalives_interval = interval ;
1361+ return STATUS_OK ;
1362+ }
1363+ #endif
1364+
13171365int
13181366pq_getkeepalivesidle (Port * port )
13191367{
1320- #if defined(TCP_KEEPIDLE ) || defined(TCP_KEEPALIVE )
1368+ #if defined(TCP_KEEPIDLE ) || defined(TCP_KEEPALIVE ) || defined( WIN32 )
13211369 if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
13221370 return 0 ;
13231371
@@ -1326,6 +1374,7 @@ pq_getkeepalivesidle(Port *port)
13261374
13271375 if (port -> default_keepalives_idle == 0 )
13281376 {
1377+ #ifndef WIN32
13291378 ACCEPT_TYPE_ARG3 size = sizeof (port -> default_keepalives_idle );
13301379
13311380#ifdef TCP_KEEPIDLE
@@ -1344,7 +1393,11 @@ pq_getkeepalivesidle(Port *port)
13441393 elog (LOG , "getsockopt(TCP_KEEPALIVE) failed: %m" );
13451394 port -> default_keepalives_idle = -1 ; /* don't know */
13461395 }
1347- #endif
1396+ #endif /* TCP_KEEPIDLE */
1397+ #else /* WIN32 */
1398+ /* We can't get the defaults on Windows, so return "don't know" */
1399+ port -> default_keepalives_idle = -1 ;
1400+ #endif /* WIN32 */
13481401 }
13491402
13501403 return port -> default_keepalives_idle ;
@@ -1359,10 +1412,11 @@ pq_setkeepalivesidle(int idle, Port *port)
13591412 if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
13601413 return STATUS_OK ;
13611414
1362- #if defined(TCP_KEEPIDLE ) || defined(TCP_KEEPALIVE )
1415+ #if defined(TCP_KEEPIDLE ) || defined(TCP_KEEPALIVE ) || defined( WIN32 )
13631416 if (idle == port -> keepalives_idle )
13641417 return STATUS_OK ;
13651418
1419+ #ifndef WIN32
13661420 if (port -> default_keepalives_idle <= 0 )
13671421 {
13681422 if (pq_getkeepalivesidle (port ) < 0 )
@@ -1394,21 +1448,23 @@ pq_setkeepalivesidle(int idle, Port *port)
13941448#endif
13951449
13961450 port -> keepalives_idle = idle ;
1397- #else
1451+ #else /* WIN32 */
1452+ return pq_setkeepaliveswin32 (port , idle , port -> keepalives_interval );
1453+ #endif
1454+ #else /* TCP_KEEPIDLE || WIN32 */
13981455 if (idle != 0 )
13991456 {
14001457 elog (LOG , "setting the keepalive idle time is not supported" );
14011458 return STATUS_ERROR ;
14021459 }
14031460#endif
1404-
14051461 return STATUS_OK ;
14061462}
14071463
14081464int
14091465pq_getkeepalivesinterval (Port * port )
14101466{
1411- #ifdef TCP_KEEPINTVL
1467+ #if defined( TCP_KEEPINTVL ) || defined( WIN32 )
14121468 if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
14131469 return 0 ;
14141470
@@ -1417,6 +1473,7 @@ pq_getkeepalivesinterval(Port *port)
14171473
14181474 if (port -> default_keepalives_interval == 0 )
14191475 {
1476+ #ifndef WIN32
14201477 ACCEPT_TYPE_ARG3 size = sizeof (port -> default_keepalives_interval );
14211478
14221479 if (getsockopt (port -> sock , IPPROTO_TCP , TCP_KEEPINTVL ,
@@ -1426,6 +1483,10 @@ pq_getkeepalivesinterval(Port *port)
14261483 elog (LOG , "getsockopt(TCP_KEEPINTVL) failed: %m" );
14271484 port -> default_keepalives_interval = -1 ; /* don't know */
14281485 }
1486+ #else
1487+ /* We can't get the defaults on Windows, so return "don't know" */
1488+ port -> default_keepalives_interval = -1 ;
1489+ #endif /* WIN32 */
14291490 }
14301491
14311492 return port -> default_keepalives_interval ;
@@ -1440,10 +1501,11 @@ pq_setkeepalivesinterval(int interval, Port *port)
14401501 if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
14411502 return STATUS_OK ;
14421503
1443- #ifdef TCP_KEEPINTVL
1504+ #if defined( TCP_KEEPINTVL ) || defined ( WIN32 )
14441505 if (interval == port -> keepalives_interval )
14451506 return STATUS_OK ;
14461507
1508+ #ifndef WIN32
14471509 if (port -> default_keepalives_interval <= 0 )
14481510 {
14491511 if (pq_getkeepalivesinterval (port ) < 0 )
@@ -1466,6 +1528,9 @@ pq_setkeepalivesinterval(int interval, Port *port)
14661528 }
14671529
14681530 port -> keepalives_interval = interval ;
1531+ #else /* WIN32 */
1532+ return pq_setkeepaliveswin32 (port , port -> keepalives_idle , interval );
1533+ #endif
14691534#else
14701535 if (interval != 0 )
14711536 {
0 commit comments