Esempio n. 1
0
void avatars_server_connection::closeConnection()
{
	stopThread = TRUE;

	mir_cslock l(localSeqMutex);
	if (hConnection)
		NetLib_SafeCloseHandle(&hConnection);
}
Esempio n. 2
0
int CIcqProto::connectNewServer(serverthread_info *info)
{
    int res = 0;

    /* Get the ip and port */
    WORD wServerPort = info->wServerPort; // prepare default port
    parseServerAddress(info->newServer, &wServerPort);

    NETLIBOPENCONNECTION nloc = {0};
    nloc.flags = 0;
    nloc.szHost = info->newServer;
    nloc.wPort = wServerPort;

    if (!m_bGatewayMode)
    {
        NetLib_SafeCloseHandle(&info->hPacketRecver);
        NetLib_CloseConnection(&hServerConn, TRUE);

        NetLog_Server("Closed connection to login server");

        hServerConn = NetLib_OpenConnection(m_hServerNetlibUser, NULL, &nloc);
        if (hServerConn && info->newServerSSL)
        {   /* Start SSL session if requested */
            if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hServerConn, 0))
                NetLib_CloseConnection(&hServerConn, FALSE);
        }

        if (hServerConn)
        {
            /* Time to recreate the packet receiver */
            info->hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400);
            if (!info->hPacketRecver)
            {
                NetLog_Server("Error: Failed to create packet receiver.");
            }
            else // we need to reset receiving structs
            {
                info->bReinitRecver = 1;
                res = 1;
            }
        }
    }
    else
    {   // TODO: We should really do some checks here
        NetLog_Server("Walking in Gateway to %s", info->newServer);
        // TODO: This REQUIRES more work (most probably some kind of mid-netlib module)
        icq_httpGatewayWalkTo(hServerConn, &nloc);
        res = 1;
    }
    if (!res) SAFE_FREE((void**)&info->cookieData);

    // Free allocated memory
    // NOTE: "cookie" will get freed when we have connected to the communication server.
    SAFE_FREE(&info->newServer);

    return res;
}
Esempio n. 3
0
void avatars_server_connection::connectionThread()
{
	// This is the "infinite" loop that receives the packets from the ICQ avatar server
	NETLIBPACKETRECVER packetRecv = { 0 };
	DWORD dwLastKeepAlive = time(0) + KEEPALIVE_INTERVAL;

	hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hConnection, 65536);
	packetRecv.cbSize = sizeof(packetRecv);
	packetRecv.dwTimeout = 1000; // timeout - for stopThread to work
	while (!stopThread) {
		int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv);
		if (recvResult == 0) {
			ppro->debugLogA("Clean closure of avatar socket");
			break;
		}

		if (recvResult == SOCKET_ERROR) {
			if (GetLastError() == ERROR_TIMEOUT) {  // timeout, check if we should be still running
				if (Miranda_Terminated())
					break;

				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);
					}
					dwLastKeepAlive = time(0) + KEEPALIVE_INTERVAL;
				}

				// check if we got something to request
				checkRequestQueue();
				continue;
			}
			if (!stopThread)
				ppro->debugLogA("Avatar socket closed abortively, error: %d", GetLastError());
			else
				ppro->debugLogA("Avatar socket gracefully closed.");
			break;
		}

		// Deal with the packet
		packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable);

		if (isActive && (packetRecv.bytesAvailable == packetRecv.bytesUsed)) // no packets pending
			checkRequestQueue(); // process request queue
	}
	{
		// release connection
		mir_cslock l(localSeqMutex);
		NetLib_SafeCloseHandle(&hPacketRecver); // Close the packet receiver
		NetLib_CloseConnection(&hConnection, FALSE); // Close the connection
	}
	{
		// release rates
		mir_cslock l(m_ratesMutex);
		delete m_rates; m_rates = NULL;
	}

	SAFE_FREE((void**)&pCookie);
}
Esempio n. 4
0
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);

	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
	while (!stopThread)
	{
		int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv);

		if (recvResult == 0)
		{
			ppro->debugLogA("Clean closure of server socket");
			break;
		}

		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;
				}
#ifdef _DEBUG
				else ppro->debugLogA("Thread is Idle.");
#endif
				if (GetTickCount() > wLastKeepAlive)
				{ // 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
#ifdef _DEBUG
					ppro->debugLogA("Thread is Forcing Idle.");
#endif
					SleepEx(500, TRUE); // wait some time, can we do anything else ??
					if (Miranda_Terminated())
					{
						stopThread = 1;
						continue;
					}
				}
				// check if we got something to request
				checkRequestQueue();
				continue;
			}
			if (!stopThread)
				ppro->debugLogA("Abortive closure of server socket, error: %d", GetLastError());
			else
				ppro->debugLogA("Connection closed.");
			break;
		}

		// Deal with the packet
		packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable);

		if (isActive && (packetRecv.bytesAvailable == packetRecv.bytesUsed)) // no packets pending
		{ // process request queue
			checkRequestQueue();
		}
	}
	{ // release connection
		icq_lock l(localSeqMutex);
		NetLib_SafeCloseHandle(&hPacketRecver); // Close the packet receiver
		NetLib_CloseConnection(&hConnection, FALSE); // Close the connection
	}

	{ // release rates
		icq_lock l(m_ratesMutex);
		SAFE_DELETE((MZeroedObject**)&m_rates);
	}

	SAFE_FREE((void**)&pCookie);
}
Esempio n. 5
0
void __cdecl CIcqProto::ServerThread(serverthread_start_info *infoParam)
{
	serverthread_info info = {0};

	info.isLoginServer = 1;
	info.wAuthKeyLen = infoParam->wPassLen;
	null_strcpy((char*)info.szAuthKey, infoParam->szPass, info.wAuthKeyLen);
	// store server port
	info.wServerPort = infoParam->nloc.wPort;

	srand(time(NULL));

	ResetSettingsOnConnect();

	// Connect to the login server
	NetLog_Server("Authenticating to server");
	{
		NETLIBOPENCONNECTION nloc = infoParam->nloc;
		nloc.timeout = 6;
		if (m_bGatewayMode)
			nloc.flags |= NLOCF_HTTPGATEWAY;

		hServerConn = NetLib_OpenConnection(m_hServerNetlibUser, NULL, &nloc);

		SAFE_FREE((void**)&nloc.szHost);
		SAFE_FREE((void**)&infoParam);

		if (hServerConn && m_bSecureConnection)
		{
			if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hServerConn, 0))
			{
				icq_LogMessage(LOG_ERROR, LPGEN("Unable to connect to ICQ login server, SSL could not be negotiated"));
				SetCurrentStatus(ID_STATUS_OFFLINE);
				NetLib_CloseConnection(&hServerConn, TRUE);
				return;
			}
		}

	}

	// Login error
	if (hServerConn == NULL)
	{
		DWORD dwError = GetLastError();

		SetCurrentStatus(ID_STATUS_OFFLINE);

		icq_LogUsingErrorCode(LOG_ERROR, dwError, LPGEN("Unable to connect to ICQ login server"));
		return;
	}

	// Initialize direct connection ports
	{
		DWORD dwInternalIP;
		BYTE bConstInternalIP = getSettingByte(NULL, "ConstRealIP", 0);

		info.hDirectBoundPort = NetLib_BindPort(icq_newConnectionReceived, this, &wListenPort, &dwInternalIP);
		if (!info.hDirectBoundPort)
		{
			icq_LogUsingErrorCode(LOG_WARNING, GetLastError(), LPGEN("Miranda was unable to allocate a port to listen for direct peer-to-peer connections between clients. You will be able to use most of the ICQ network without problems but you may be unable to send or receive files.\n\nIf you have a firewall this may be blocking Miranda, in which case you should configure your firewall to leave some ports open and tell Miranda which ports to use in M->Options->ICQ->Network."));
			wListenPort = 0;
			if (!bConstInternalIP) deleteSetting(NULL, "RealIP");
		}
		else if (!bConstInternalIP)
			setSettingDword(NULL, "RealIP", dwInternalIP);
	}

	// Initialize rate limiting queues
	{ 
		icq_lock l(m_ratesMutex);

		m_ratesQueue_Request = new rates_queue(this, "request", RML_IDLE_30, RML_IDLE_50, 1);
		m_ratesQueue_Response = new rates_queue(this, "response", RML_IDLE_10, RML_IDLE_30, -1);
	}

	// This is the "infinite" loop that receives the packets from the ICQ server
	{
		int recvResult;
		NETLIBPACKETRECVER packetRecv = {0};

		info.hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400);
		packetRecv.cbSize = sizeof(packetRecv);
		packetRecv.dwTimeout = INFINITE;
		while (serverThreadHandle)
		{
			if (info.bReinitRecver)
			{ // we reconnected, reinit struct
				info.bReinitRecver = 0;
				ZeroMemory(&packetRecv, sizeof(packetRecv));
				packetRecv.cbSize = sizeof(packetRecv);
				packetRecv.dwTimeout = INFINITE;
			}

			recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)info.hPacketRecver, (LPARAM)&packetRecv);

			if (recvResult == 0)
			{
				NetLog_Server("Clean closure of server socket");
				break;
			}

			if (recvResult == SOCKET_ERROR)
			{
				NetLog_Server("Abortive closure of server socket, error: %d", GetLastError());
				break;
			}

			if (m_iDesiredStatus == ID_STATUS_OFFLINE)
			{ // Disconnect requested, send disconnect packet
				icq_sendCloseConnection();

				// disconnected upon request
				m_bConnectionLost = FALSE;
				SetCurrentStatus(ID_STATUS_OFFLINE);

				NetLog_Server("Logged off.");
				break;
			}

			// Deal with the packet
			packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable, &info);
		}
		serverThreadHandle = NULL;

		// Time to shutdown
		NetLib_CloseConnection(&hServerConn, TRUE);

		// Close the packet receiver (connection may still be open)
		NetLib_SafeCloseHandle(&info.hPacketRecver);

		// Close DC port
		NetLib_SafeCloseHandle(&info.hDirectBoundPort);
	}

	// disable auto info-update thread
	icq_EnableUserLookup(FALSE);

	if (m_iStatus != ID_STATUS_OFFLINE && m_iDesiredStatus != ID_STATUS_OFFLINE)
	{
		if (!info.bLoggedIn)
			icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nLogin sequence failed for unknown reason.\nTry again later."));

		// set flag indicating we were kicked out
		m_bConnectionLost = TRUE;

		SetCurrentStatus(ID_STATUS_OFFLINE);
	}

	// signal keep-alive thread to stop
	StopKeepAlive(&info);

	// Close all open DC connections
	CloseContactDirectConns(NULL);

	// Close avatar connection if any
	StopAvatarThread();

	// Offline all contacts
	HANDLE hContact = FindFirstContact();
	while (hContact)
	{
		DWORD dwUIN;
		uid_str szUID;

		if (!getContactUid(hContact, &dwUIN, &szUID))
		{
			if (getContactStatus(hContact) != ID_STATUS_OFFLINE)
			{
				char tmp = 0;

				setSettingWord(hContact, "Status", ID_STATUS_OFFLINE);

				handleXStatusCaps(dwUIN, szUID, hContact, (BYTE*)&tmp, 0, &tmp, 0);
			}
		}

		hContact = FindNextContact(hContact);
	}

	setSettingDword(NULL, "LogonTS", 0); // clear logon time

	servlistPendingFlushOperations(); // clear pending operations list

	{ // release rates queues
		icq_lock l(m_ratesMutex);

		SAFE_DELETE((void_struct**)&m_ratesQueue_Request);
		SAFE_DELETE((void_struct**)&m_ratesQueue_Response);
		SAFE_DELETE((void_struct**)&m_rates);
	}

	FlushServerIDs();         // clear server IDs list

	NetLog_Server("%s thread ended.", "Server");
}