From 0d0add7b1272241fe4c90f09c7ca8be1762a3c6d Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Wed, 16 Jul 2014 11:17:06 +0000
Subject: fix for keep-alive in ICQ

git-svn-id: http://svn.miranda-ng.org/main/trunk@9827 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 protocols/IcqOscarJ/src/chan_05ping.cpp | 24 ++++++++++++------------
 protocols/IcqOscarJ/src/icq_avatar.cpp  | 28 +++++++++-------------------
 protocols/IcqOscarJ/src/icq_constants.h |  2 +-
 protocols/IcqOscarJ/src/icq_server.cpp  |  4 +++-
 protocols/IcqOscarJ/src/icq_server.h    | 28 ++++++++++++++--------------
 protocols/IcqOscarJ/src/version.h       |  2 +-
 6 files changed, 40 insertions(+), 48 deletions(-)

(limited to 'protocols')

diff --git a/protocols/IcqOscarJ/src/chan_05ping.cpp b/protocols/IcqOscarJ/src/chan_05ping.cpp
index 5fe2aaf9a7..8e735337e8 100644
--- a/protocols/IcqOscarJ/src/chan_05ping.cpp
+++ b/protocols/IcqOscarJ/src/chan_05ping.cpp
@@ -32,27 +32,27 @@ void CIcqProto::handlePingChannel(BYTE *buf, WORD datalen)
 void CIcqProto::StartKeepAlive(serverthread_info *info)
 {
 	if (getByte("KeepAlive", DEFAULT_KEEPALIVE_ENABLED))
-		info->iKeepalive = getDword("KeepAliveInterval", KEEPALIVE_INTERVAL);
+		info->tmPing = time(0) + KEEPALIVE_INTERVAL;
 	else
-		info->iKeepalive = -1;
+		info->tmPing = -1;
 }
 
 void CIcqProto::StopKeepAlive(serverthread_info *info)
 {
-	info->iKeepalive = -1;
+	info->tmPing = -1;
 }
 
 void CIcqProto::CheckKeepAlive(serverthread_info *info)
 {
-	if (info->iKeepalive != -1) {
-		if (info->iKeepalive == 0) {
-			// Send a keep alive packet to server
-			icq_packet packet = { 0 };
-			write_flap(&packet, ICQ_PING_CHAN);
-			sendServPacket(&packet);
+	if (info->tmPing == -1)
+		return;
 
-			StartKeepAlive(info);
-		}
-		else info->iKeepalive--;
+	if (time(0) >= info->tmPing) {
+		// Send a keep alive packet to server
+		icq_packet packet = { 0 };
+		write_flap(&packet, ICQ_PING_CHAN);
+		sendServPacket(&packet);
+
+		StartKeepAlive(info);
 	}
 }
diff --git a/protocols/IcqOscarJ/src/icq_avatar.cpp b/protocols/IcqOscarJ/src/icq_avatar.cpp
index f71b32ede0..35bcd7de2a 100644
--- a/protocols/IcqOscarJ/src/icq_avatar.cpp
+++ b/protocols/IcqOscarJ/src/icq_avatar.cpp
@@ -941,12 +941,11 @@ void avatars_server_connection::connectionThread()
 {
 	// This is the "infinite" loop that receives the packets from the ICQ avatar server
 	NETLIBPACKETRECVER packetRecv = { 0 };
-	DWORD wLastKeepAlive = 0; // we send keep-alive at most one per 30secs
-	DWORD dwKeepAliveInterval = ppro->getDword("KeepAliveInterval", KEEPALIVE_INTERVAL);
+	DWORD dwLastKeepAlive = time(0) + KEEPALIVE_INTERVAL;
 
 	hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hConnection, 65536);
 	packetRecv.cbSize = sizeof(packetRecv);
-	packetRecv.dwTimeout = dwKeepAliveInterval < KEEPALIVE_INTERVAL ? dwKeepAliveInterval: KEEPALIVE_INTERVAL; // timeout - for stopThread to work
+	packetRecv.dwTimeout = 1000; // timeout - for stopThread to work
 	while (!stopThread) {
 		int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv);
 		if (recvResult == 0) {
@@ -956,36 +955,27 @@ void avatars_server_connection::connectionThread()
 
 		if (recvResult == SOCKET_ERROR) {
 			if (GetLastError() == ERROR_TIMEOUT) {  // timeout, check if we should be still running
-				if (Miranda_Terminated()) { // we must stop here, cause due to a hack in netlib, we always get timeout, even if the connection is already dead
-					stopThread = 1;
-					continue;
-				}
+				if (Miranda_Terminated())
+					break;
 
-				if (GetTickCount() > wLastKeepAlive) { // limit frequency (HACK: on some systems select() does not work well)
+				if (time(0) >= dwLastKeepAlive) { // limit frequency (HACK: on some systems select() does not work well)
 					if (!ppro->m_bGatewayMode && ppro->getByte("KeepAlive", DEFAULT_KEEPALIVE_ENABLED)) { // send keep-alive packet
 						icq_packet packet;
-
 						packet.wLen = 0;
 						write_flap(&packet, ICQ_PING_CHAN);
 						sendServerPacket(&packet);
 					}
-					wLastKeepAlive = GetTickCount() + dwKeepAliveInterval;
-				}
-				else { // this is bad, the system does not handle select() properly
-					SleepEx(500, TRUE); // wait some time, can we do anything else ??
-					if (Miranda_Terminated()) {
-						stopThread = 1;
-						continue;
-					}
+					dwLastKeepAlive = time(0) + KEEPALIVE_INTERVAL;
 				}
+
 				// check if we got something to request
 				checkRequestQueue();
 				continue;
 			}
 			if (!stopThread)
-				ppro->debugLogA("Abortive closure of server socket, error: %d", GetLastError());
+				ppro->debugLogA("Avatar socket closed abortively, error: %d", GetLastError());
 			else
-				ppro->debugLogA("Connection closed.");
+				ppro->debugLogA("Avatar socket gracefully closed.");
 			break;
 		}
 
diff --git a/protocols/IcqOscarJ/src/icq_constants.h b/protocols/IcqOscarJ/src/icq_constants.h
index d4ef7d72ac..1935cded25 100644
--- a/protocols/IcqOscarJ/src/icq_constants.h
+++ b/protocols/IcqOscarJ/src/icq_constants.h
@@ -624,7 +624,7 @@
 #define MAX_MESSAGESNACSIZE         8000
 #define CLIENTRATELIMIT             0
 #define COOKIE_TIMEOUT              3600      // One hour
-#define KEEPALIVE_INTERVAL          57000     // One minute
+#define KEEPALIVE_INTERVAL          57        // Slightly less than a minute
 #define WEBFRONTPORT                0x50
 #define CLIENTFEATURES              0x3
 #define URL_FORGOT_PASSWORD         "https://www.icq.com/password/"
diff --git a/protocols/IcqOscarJ/src/icq_server.cpp b/protocols/IcqOscarJ/src/icq_server.cpp
index 5c7d5368ef..dccf6996cb 100644
--- a/protocols/IcqOscarJ/src/icq_server.cpp
+++ b/protocols/IcqOscarJ/src/icq_server.cpp
@@ -101,6 +101,8 @@ void __cdecl CIcqProto::ServerThread(serverthread_start_info *infoParam)
 		m_ratesQueue_Response = new rates_queue(this, "response", RML_IDLE_10, RML_IDLE_30, -1);
 	}
 
+	StartKeepAlive(&info);
+
 	// This is the "infinite" loop that receives the packets from the ICQ server
 	NETLIBPACKETRECVER packetRecv;
 	info.hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400);
@@ -136,6 +138,7 @@ void __cdecl CIcqProto::ServerThread(serverthread_start_info *infoParam)
 		}
 
 		// Deal with the packet
+		CheckKeepAlive(&info);
 		packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable, &info);
 	}
 	serverThreadHandle = NULL;
@@ -322,7 +325,6 @@ void CIcqProto::sendServPacket(icq_packet *pPacket)
 			icq_lock l(m_ratesMutex);
 			m_rates->packetSent(pPacket);
 		}
-
 	}
 	else {
 		connectionHandleMutex->Leave();
diff --git a/protocols/IcqOscarJ/src/icq_server.h b/protocols/IcqOscarJ/src/icq_server.h
index b485b29c79..99b545b14e 100644
--- a/protocols/IcqOscarJ/src/icq_server.h
+++ b/protocols/IcqOscarJ/src/icq_server.h
@@ -39,21 +39,21 @@ struct serverthread_start_info
 
 struct serverthread_info
 {
-	BYTE szAuthKey[20];
-	WORD wAuthKeyLen;
-	WORD wServerPort;
-	char *newServer;
-	BYTE *cookieData;
-	int  cookieDataLen;
-	int  newServerSSL;
-	int  iKeepalive;
+	BYTE   szAuthKey[20];
+	WORD   wAuthKeyLen;
+	WORD   wServerPort;
+	char   *newServer;
+	BYTE   *cookieData;
+	int    cookieDataLen;
+	int    newServerSSL;
+	time_t tmPing;        // timestamp of the next ping
 
-	bool isLoginServer;
-	bool isMigrating;
-	bool isNewServerReady;
-	bool bLoggedIn;
-	bool bReinitRecver;
-	bool bMyAvatarInited;
+	bool   isLoginServer;
+	bool   isMigrating;
+	bool   isNewServerReady;
+	bool   bLoggedIn;
+	bool   bReinitRecver;
+	bool   bMyAvatarInited;
 
 	HANDLE hPacketRecver;
 	HANDLE hDirectBoundPort;
diff --git a/protocols/IcqOscarJ/src/version.h b/protocols/IcqOscarJ/src/version.h
index 54c9dfc2a5..5f7bdf2dec 100644
--- a/protocols/IcqOscarJ/src/version.h
+++ b/protocols/IcqOscarJ/src/version.h
@@ -1,7 +1,7 @@
 #define __MAJOR_VERSION          0
 #define __MINOR_VERSION          11
 #define __RELEASE_NUM            2
-#define __BUILD_NUM              4
+#define __BUILD_NUM              5
 
 #include <stdver.h>
 
-- 
cgit v1.2.3