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 )
13211369if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
13221370return 0 ;
13231371
@@ -1326,6 +1374,7 @@ pq_getkeepalivesidle(Port *port)
13261374
13271375if (port -> default_keepalives_idle == 0 )
13281376{
1377+ #ifndef WIN32
13291378ACCEPT_TYPE_ARG3 size = sizeof (port -> default_keepalives_idle );
13301379
13311380#ifdef TCP_KEEPIDLE
@@ -1344,7 +1393,11 @@ pq_getkeepalivesidle(Port *port)
13441393elog (LOG ,"getsockopt(TCP_KEEPALIVE) failed: %m" );
13451394port -> 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
13501403return port -> default_keepalives_idle ;
@@ -1359,10 +1412,11 @@ pq_setkeepalivesidle(int idle, Port *port)
13591412if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
13601413return STATUS_OK ;
13611414
1362- #if defined(TCP_KEEPIDLE )|| defined(TCP_KEEPALIVE )
1415+ #if defined(TCP_KEEPIDLE )|| defined(TCP_KEEPALIVE )|| defined( WIN32 )
13631416if (idle == port -> keepalives_idle )
13641417return STATUS_OK ;
13651418
1419+ #ifndef WIN32
13661420if (port -> default_keepalives_idle <=0 )
13671421{
13681422if (pq_getkeepalivesidle (port )< 0 )
@@ -1394,21 +1448,23 @@ pq_setkeepalivesidle(int idle, Port *port)
13941448#endif
13951449
13961450port -> keepalives_idle = idle ;
1397- #else
1451+ #else /* WIN32 */
1452+ return pq_setkeepaliveswin32 (port ,idle ,port -> keepalives_interval );
1453+ #endif
1454+ #else /* TCP_KEEPIDLE || WIN32 */
13981455if (idle != 0 )
13991456{
14001457elog (LOG ,"setting the keepalive idle time is not supported" );
14011458return STATUS_ERROR ;
14021459}
14031460#endif
1404-
14051461return STATUS_OK ;
14061462}
14071463
14081464int
14091465pq_getkeepalivesinterval (Port * port )
14101466{
1411- #ifdef TCP_KEEPINTVL
1467+ #if defined( TCP_KEEPINTVL ) || defined( WIN32 )
14121468if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
14131469return 0 ;
14141470
@@ -1417,6 +1473,7 @@ pq_getkeepalivesinterval(Port *port)
14171473
14181474if (port -> default_keepalives_interval == 0 )
14191475{
1476+ #ifndef WIN32
14201477ACCEPT_TYPE_ARG3 size = sizeof (port -> default_keepalives_interval );
14211478
14221479if (getsockopt (port -> sock ,IPPROTO_TCP ,TCP_KEEPINTVL ,
@@ -1426,6 +1483,10 @@ pq_getkeepalivesinterval(Port *port)
14261483elog (LOG ,"getsockopt(TCP_KEEPINTVL) failed: %m" );
14271484port -> 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
14311492return port -> default_keepalives_interval ;
@@ -1440,10 +1501,11 @@ pq_setkeepalivesinterval(int interval, Port *port)
14401501if (port == NULL || IS_AF_UNIX (port -> laddr .addr .ss_family ))
14411502return STATUS_OK ;
14421503
1443- #ifdef TCP_KEEPINTVL
1504+ #if defined( TCP_KEEPINTVL ) || defined ( WIN32 )
14441505if (interval == port -> keepalives_interval )
14451506return STATUS_OK ;
14461507
1508+ #ifndef WIN32
14471509if (port -> default_keepalives_interval <=0 )
14481510{
14491511if (pq_getkeepalivesinterval (port )< 0 )
@@ -1466,6 +1528,9 @@ pq_setkeepalivesinterval(int interval, Port *port)
14661528}
14671529
14681530port -> keepalives_interval = interval ;
1531+ #else /* WIN32 */
1532+ return pq_setkeepaliveswin32 (port ,port -> keepalives_idle ,interval );
1533+ #endif
14691534#else
14701535if (interval != 0 )
14711536{