void __cdecl CMsnProto::MSNServerThread(void* arg) { ThreadData* info = (ThreadData*)arg; if (info->mIsMainThread) isConnectSuccess = false; int tPortNumber = -1; { char* tPortDelim = strrchr(info->mServer, ':'); if (tPortDelim != NULL) { *tPortDelim = '\0'; if ((tPortNumber = atoi(tPortDelim + 1)) == 0) tPortNumber = -1; else if (usingGateway && !(tPortNumber == 80 || tPortNumber == 443)) usingGateway = false; } } if (usingGateway) { if (info->mServer[0] == 0) mir_strcpy(info->mServer, MSN_DEFAULT_LOGIN_SERVER); else if (info->mIsMainThread) mir_strcpy(info->mGatewayIP, info->mServer); if (info->gatewayType) mir_strcpy(info->mGatewayIP, info->mServer); else { if (info->mGatewayIP[0] == 0 && db_get_static(NULL, m_szModuleName, "GatewayServer", info->mGatewayIP, sizeof(info->mGatewayIP))) mir_strcpy(info->mGatewayIP, MSN_DEFAULT_GATEWAY); } } else { if (info->mServer[0] == 0 && db_get_static(NULL, m_szModuleName, "DirectServer", info->mServer, sizeof(info->mServer))) mir_strcpy(info->mServer, MSN_DEFAULT_LOGIN_SERVER); } NETLIBOPENCONNECTION tConn = { 0 }; tConn.cbSize = sizeof(tConn); tConn.flags = NLOCF_V2; tConn.timeout = 5; if (usingGateway) { tConn.flags |= NLOCF_HTTPGATEWAY; tConn.szHost = info->mGatewayIP; tConn.wPort = MSN_DEFAULT_GATEWAY_PORT; } else { tConn.flags = NLOCF_SSL; tConn.szHost = info->mServer; tConn.wPort = MSN_DEFAULT_PORT; } if (tPortNumber != -1) tConn.wPort = (WORD)tPortNumber; debugLogA("Thread started: server='%s:%d', type=%d", tConn.szHost, tConn.wPort, info->mType); info->s = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)m_hNetlibUser, (LPARAM)&tConn); if (info->s == NULL) { debugLogA("Connection Failed (%d) server='%s:%d'", WSAGetLastError(), tConn.szHost, tConn.wPort); switch (info->mType) { case SERVER_NOTIFICATION: goto LBL_Exit; break; case SERVER_SWITCHBOARD: if (info->mCaller) msnNsThread->sendPacket("XFR", "SB"); break; } return; } if (usingGateway) CallService(MS_NETLIB_SETPOLLINGTIMEOUT, WPARAM(info->s), info->mGatewayTimeout); debugLogA("Connected with handle=%08X", info->s); if (info->mType == SERVER_NOTIFICATION) info->sendPacketPayload("CNT", "CON", "<connect>%s%s%s<ver>2</ver><agent><os>winnt</os><osVer>5.2</osVer><proc>x86</proc><lcid>en-us</lcid></agent></connect>\r\n", *info->mState?"<xfr><state>":"", *info->mState?info->mState:"", *info->mState?"</state></xfr>":""); else if (info->mType == SERVER_SWITCHBOARD) { info->sendPacket(info->mCaller ? "USR" : "ANS", "%s;%s %s", MyOptions.szEmail, MyOptions.szMachineGuid, info->mCookie); } else if (info->mType == SERVER_FILETRANS && info->mCaller == 0) { info->send("VER MSNFTP\r\n", 12); } if (info->mIsMainThread) { msnNsThread = info; } debugLogA("Entering main recv loop"); info->mBytesInData = 0; for (;;) { int recvResult = info->recv(info->mData + info->mBytesInData, info->mDataSize - info->mBytesInData); if (recvResult == SOCKET_ERROR) { debugLogA("Connection %08p [%08X] was abortively closed", info->s, GetCurrentThreadId()); break; } if (!recvResult) { debugLogA("Connection %08p [%08X] was gracefully closed", info->s, GetCurrentThreadId()); break; } info->mBytesInData += recvResult; #ifdef OBSOLETE if (info->mCaller == 1 && info->mType == SERVER_FILETRANS) { if (MSN_HandleMSNFTP(info, info->mData)) break; } else #endif { for (;;) { char* peol = strchr(info->mData, '\r'); if (peol == NULL) break; int msgLen = (int)(peol - info->mData); if (info->mBytesInData < msgLen + 2) break; //wait for full line end char msg[1024]; strncpy_s(msg, info->mData, msgLen); if (*++peol != '\n') debugLogA("Dodgy line ending to command: ignoring"); else peol++; info->mBytesInData -= peol - info->mData; memmove(info->mData, peol, info->mBytesInData); debugLogA("RECV: %s", msg); if (!isalnum(msg[0]) || !isalnum(msg[1]) || !isalnum(msg[2]) || (msg[3] && msg[3] != ' ')) { debugLogA("Invalid command name"); continue; } if (info->mType != SERVER_FILETRANS) { int handlerResult; if (isdigit(msg[0]) && isdigit(msg[1]) && isdigit(msg[2])) //all error messages handlerResult = MSN_HandleErrors(info, msg); else handlerResult = MSN_HandleCommands(info, msg); if (handlerResult) { if (info->sessionClosed) goto LBL_Exit; info->sendTerminate(); } } #ifdef OBSOLETE else if (MSN_HandleMSNFTP(info, msg)) goto LBL_Exit; #endif } } if (info->mBytesInData == info->mDataSize) { if (!ReallocInfoBuffer(info, info->mDataSize*2)) { debugLogA("sizeof(data) is too small: the longest line won't fit"); break; } } } LBL_Exit: if (info->mIsMainThread) { /* if (!isConnectSuccess && !usingGateway && m_iDesiredStatus != ID_STATUS_OFFLINE) { msnNsThread = NULL; usingGateway = true; ThreadData* newThread = new ThreadData; newThread->mType = SERVER_NOTIFICATION; newThread->mIsMainThread = true; newThread->startThread(&CMsnProto::MSNServerThread, this); } else*/ { if (hKeepAliveThreadEvt) { msnPingTimeout *= -1; SetEvent(hKeepAliveThreadEvt); } if (info->s == NULL) ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NONETWORK); else { #ifdef OBSOLETE p2p_cancelAllSessions(); #endif MSN_CloseConnections(); } if (hHttpsConnection) { Netlib_CloseHandle(hHttpsConnection); hHttpsConnection = NULL; } MSN_GoOffline(); msnNsThread = NULL; } } debugLogA("Thread [%08X] ending now", GetCurrentThreadId()); }
void __cdecl MSNServerThread( ThreadData* info ) { if ( !sttRedirectorWasChecked ) { sttRedirectorWasChecked = true; MSN_StartThread(( pThreadFunc )msn_RedirectorThread, NULL ); } NETLIBOPENCONNECTION tConn = { 0 }; tConn.cbSize = sizeof( tConn ); tConn.flags = NLOCF_V2; char* tPortDelim = strrchr( info->mServer, ':' ); if ( tPortDelim != NULL ) *tPortDelim = '\0'; if ( MyOptions.UseGateway && !MyOptions.UseProxy ) { tConn.szHost = MSN_DEFAULT_GATEWAY; tConn.wPort = 80; } else { tConn.szHost = info->mServer; tConn.wPort = MSN_DEFAULT_PORT; if ( tPortDelim != NULL ) { int tPortNumber; if ( sscanf( tPortDelim+1, "%d", &tPortNumber ) == 1 ) tConn.wPort = ( WORD )tPortNumber; } } MSN_DebugLog( "Thread started: server='%s', type=%d", tConn.szHost, info->mType ); info->s = ( HANDLE )MSN_CallService( MS_NETLIB_OPENCONNECTION, ( WPARAM )hNetlibUser, ( LPARAM )&tConn ); if ( info->s == NULL ) { MSN_DebugLog( "Connection Failed (%d)", WSAGetLastError() ); switch ( info->mType ) { case SERVER_NOTIFICATION: case SERVER_DISPATCH: MSN_SendBroadcast( NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER ); MSN_GoOffline(); break; } return; } if ( MyOptions.UseGateway ) MSN_CallService( MS_NETLIB_SETPOLLINGTIMEOUT, WPARAM( info->s ), 2 ); MSN_DebugLog( "Connected with handle=%08X", info->s ); if ( info->mType == SERVER_DISPATCH || info->mType == SERVER_NOTIFICATION ) { if ( MyOptions.UseMSNP11 ) info->sendPacket( "VER", "MSNP11 MSNP10 CVR0" ); else info->sendPacket( "VER", "MSNP10 MSNP9 CVR0" ); } else if ( info->mType == SERVER_SWITCHBOARD ) { char tEmail[ MSN_MAX_EMAIL_LEN ]; MSN_GetStaticString( "e-mail", NULL, tEmail, sizeof( tEmail )); info->sendPacket( info->mCaller ? "USR" : "ANS", "%s %s", tEmail, info->mCookie ); } else if ( info->mType == SERVER_FILETRANS && info->mCaller == 0 ) { info->send( "VER MSNFTP\r\n", 12 ); } if ( info->mIsMainThread ) { MSN_EnableMenuItems( TRUE ); msnPingTimeout = msnPingTimeoutCurrent; msnNsThread = info; if (hKeepAliveThreadEvt == NULL) { hKeepAliveThreadEvt = ::CreateEvent( NULL, TRUE, FALSE, NULL ); MSN_StartThread(( pThreadFunc )msn_keepAliveThread, NULL ); } } MSN_DebugLog( "Entering main recv loop" ); info->mBytesInData = 0; while ( TRUE ) { int handlerResult; int recvResult = info->recv( info->mData + info->mBytesInData, sizeof( info->mData ) - info->mBytesInData ); if ( recvResult == SOCKET_ERROR ) { MSN_DebugLog( "Connection %08p [%d] was abortively closed", info->s, GetCurrentThreadId()); break; } if ( !recvResult ) { MSN_DebugLog( "Connection %08p [%d] was gracefully closed", info->s, GetCurrentThreadId()); break; } info->mBytesInData += recvResult; if ( info->mCaller == 1 && info->mType == SERVER_FILETRANS ) { handlerResult = MSN_HandleMSNFTP( info, info->mData ); if ( handlerResult ) break; } else { while( TRUE ) { char* peol = strchr(info->mData,'\r'); if ( peol == NULL ) break; if ( info->mBytesInData < peol-info->mData+2 ) break; //wait for full line end char msg[ sizeof(info->mData) ]; memcpy( msg, info->mData, peol-info->mData ); msg[ peol-info->mData ] = 0; if ( *++peol != '\n' ) MSN_DebugLog( "Dodgy line ending to command: ignoring" ); else peol++; info->mBytesInData -= peol - info->mData; memmove( info->mData, peol, info->mBytesInData ); MSN_DebugLog( "RECV:%s", msg ); if ( !isalnum( msg[0] ) || !isalnum(msg[1]) || !isalnum(msg[2]) || (msg[3] && msg[3]!=' ')) { MSN_DebugLog( "Invalid command name" ); continue; } if ( info->mType != SERVER_FILETRANS ) { if ( isdigit(msg[0]) && isdigit(msg[1]) && isdigit(msg[2])) //all error messages handlerResult = MSN_HandleErrors( info, msg ); else handlerResult = MSN_HandleCommands( info, msg ); } else handlerResult = MSN_HandleMSNFTP( info, msg ); if ( handlerResult ) goto LBL_Exit; } } if ( info->mBytesInData == sizeof( info->mData )) { MSN_DebugLog( "sizeof(data) is too small: the longest line won't fit" ); break; } } LBL_Exit: if ( info->mIsMainThread ) { MSN_GoOffline(); msnNsThread = NULL; if ( hKeepAliveThreadEvt ) SetEvent( hKeepAliveThreadEvt ); } MSN_DebugLog( "Thread [%d] ending now", GetCurrentThreadId() ); }