EnIocpAction CUdpServer::CheckIocpCommand(OVERLAPPED* pOverlapped, DWORD dwBytes, ULONG_PTR ulCompKey) { EnIocpAction action = IOCP_ACT_GOON; if(pOverlapped == nullptr) { if(dwBytes == IOCP_CMD_SEND) { DoSend((CONNID)ulCompKey); action = IOCP_ACT_CONTINUE; } else if(dwBytes == IOCP_CMD_ACCEPT) { DoAccept(); action = IOCP_ACT_CONTINUE; } else if(dwBytes == IOCP_CMD_DISCONNECT) { ForceDisconnect((CONNID)ulCompKey); action = IOCP_ACT_CONTINUE; } else if(dwBytes == IOCP_CMD_EXIT && ulCompKey == 0) action = IOCP_ACT_BREAK; else VERIFY(FALSE); } return action; }
void CNetLink::OnLinkStart() { FUNCTION_BEGIN; if(m_pView==NULL) { POSITION Pos=CRemoteConsoleApp::GetInstance()->GetFirstDocTemplatePosition(); CDocTemplate* pTemplate=CRemoteConsoleApp::GetInstance()->GetNextDocTemplate(Pos); if(pTemplate==NULL) { ForceDisconnect(); return; } CFrameWnd * pFrame=pTemplate->CreateNewFrame(NULL,NULL); CEasyString Title; Title.Format("%s:%u",GetRemoteAddress().GetIPString(),GetRemoteAddress().GetPort()); pFrame->SetTitle(Title); pTemplate->InitialUpdateFrame(pFrame,NULL); m_pView=(CRemoteConsoleView *)pFrame->GetActiveView(); m_pView->SetNetLink(this); } CClassifiedID ID=GetID(); Log("建立与[%s][%s:%u]的连接", ID.ToStr(), GetRemoteAddress().GetIPString(), GetRemoteAddress().GetPort()); SendMsg(SC_MSG_LINK_LOG); FUNCTION_END; }
//-------------------------------------------------------------------------- void Connection::UpdateForeground() { for(VeUInt32 i(0); i < m_kPacketCache.Size(); ++i) { Packet* pkPacket = m_kPacketCache[i]; BitStream kStream((unsigned char*)pkPacket->data, pkPacket->length, false); VeUInt8 u8Event; kStream >> u8Event; switch(u8Event) { case ID_DISCONNECTION_NOTIFICATION: ConnectFailed(CONNECT_FAIL_NORMAL); break; case ID_REMOTE_CONNECTION_LOST: ConnectFailed(CONNECT_FAIL_NORMAL); break; case ID_CONNECTION_BANNED: ConnectFailed(CONNECT_FAIL_SERVER_FULL); break; case ID_NO_FREE_INCOMING_CONNECTIONS: ConnectFailed(CONNECT_FAIL_SERVER_FULL); break; case ID_CONNECTION_LOST: ConnectFailed(CONNECT_FAIL_NORMAL); break; case ID_CONNECTION_REQUEST_ACCEPTED: VE_ASSERT(!(m_pkServer->IsServerConnected())); m_pkServer->SetServerID(pkPacket->systemAddress); m_pkServer->OnConnect(); break; case ID_CONNECTION_ATTEMPT_FAILED: ConnectFailed(CONNECT_FAIL_NORMAL); break; case ID_CLIENT_GLOBAL_RPC: m_pkServer->OnGlobalRPCCallback(kStream); break; case ID_CLIENT_ENTITY_RPC: m_pkServer->OnEntityRPCCallback(kStream); break; case ID_CLIENT_ENTITY_UPDATE: m_pkServer->EntityUpdate(kStream); break; case ID_CLIENT_ENTITY_DESTORY: m_pkServer->EntityDestory(kStream); break; case ID_CLIENT_FORCE_DISCONNECT: ForceDisconnect(CONNECT_FORCE_OFF); break; default: break; } m_pkPeer->DeallocatePacket(pkPacket); } m_kPacketCache.Clear(); }
void TClient::OnConnected(bool success) { switch (CurrentState) { case CS_Logining: { if (!success) { ForceDisconnect(); Config.LoginResultCallback(LR_ConnectionFail); return; } string data; data.push_back((char)RT_Login); UdtClient->Send(data); } break; case CS_Registering: { if (!success) { ForceDisconnect(); Config.RegisterResultCallback(RR_ConnectionFailure); return; } string data; data.push_back((char)RT_Register); UdtClient->Send(data); } break; case CS_Connecting: { if (!success) { // todo: try to reconnect several times to different servers UdtClient->Disconnect(); CurrentState = CS_Disconnected; Config.ConnectedCallback(success); } string data; data.push_back((char)RT_Authorize); UdtClient->Send(data); break; } default: assert(false && "unknown state"); break; } }
EnIocpAction CTcpAgent::CheckIocpCommand(OVERLAPPED* pOverlapped, DWORD dwBytes, ULONG_PTR ulCompKey) { ASSERT(pOverlapped == nullptr); EnIocpAction action = IOCP_ACT_CONTINUE; if(dwBytes == IOCP_CMD_SEND) DoSend((CONNID)ulCompKey); else if(dwBytes == IOCP_CMD_DISCONNECT) ForceDisconnect((CONNID)ulCompKey); else if(dwBytes == IOCP_CMD_EXIT && ulCompKey == 0) action = IOCP_ACT_BREAK; else VERIFY(FALSE); return action; }
EnIocpAction CTcpServer::CheckIocpCommand(OVERLAPPED* pOverlapped, DWORD dwBytes, ULONG_PTR ulCompKey) { ASSERT(pOverlapped == nullptr); EnIocpAction action = IOCP_ACT_CONTINUE; CONNID dwConnID = (CONNID)ulCompKey; switch(dwBytes) { case IOCP_CMD_SEND : DoSend(dwConnID) ; break; case IOCP_CMD_ACCEPT : DoAccept() ; break; case IOCP_CMD_DISCONNECT: ForceDisconnect(dwConnID) ; break; case IOCP_CMD_EXIT : action = IOCP_ACT_BREAK ; break; default : CheckError(FindSocketObj(dwConnID), SO_CLOSE, (int)dwBytes); } return action; }
int CTcpServer::CheckSpecialIndative(OVERLAPPED* pOverlapped, DWORD dwBytes, TSocketObj* pSocketObj) { int indative = 0; if(pOverlapped == nullptr) { if(dwBytes == IOCP_SI_ACCEPT) { DoAccept(); indative = IOCP_SI_RS_CONTINUE; } else if(dwBytes == IOCP_SI_DISCONNECT) { ForceDisconnect((CONNID)pSocketObj); indative = IOCP_SI_RS_CONTINUE; } else if(dwBytes == IOCP_SI_EXIT && pSocketObj == nullptr) indative = IOCP_SI_RS_BREAK; else VERIFY(FALSE); } return indative; }
int CUdpServer::CheckSpecialIndative(OVERLAPPED* pOverlapped, DWORD dwBytes, ULONG_PTR ulCompKey) { int indative = IOCP_SI_RS_GONO; if(pOverlapped == nullptr) { if(dwBytes == IOCP_SI_ACCEPT) { DoAccept(); indative = IOCP_SI_RS_CONTINUE; } else if(dwBytes == IOCP_SI_DISCONNECT) { ForceDisconnect((CONNID)ulCompKey); indative = IOCP_SI_RS_CONTINUE; } else if(dwBytes == IOCP_SI_EXIT && ulCompKey == 0) indative = IOCP_SI_RS_BREAK; else VERIFY(FALSE); } return indative; }
void TClient::OnDataReceived(const TBuffer& data) { switch (CurrentState) { case CS_Registering: { Buffer += data.ToString(); string packetStr; if (Deserialize(Buffer, packetStr)) { packetStr = Decompress(packetStr); TServerRegisterPacket packet; if (!packet.ParseFromString(packetStr)) { ForceDisconnect(); Config.RegisterResultCallback(RR_ConnectionFailure); return; } string captcha = packet.captcha(); State.set_serverpublickey(packet.publickey()); Config.CaptchaAvailableCallback(captcha); } } break; case CS_RegisteringConfirmWait: { Buffer += data.ToString(); string packetStr; if (Deserialize(Buffer, packetStr)) { packetStr = Decompress(DecryptAsymmetrical(State.privatekey(), packetStr)); if (packetStr.size() != 1) { ForceDisconnect(); Config.RegisterResultCallback(RR_ConnectionFailure); return; } ERegisterResult registerResult; registerResult = (ERegisterResult)packetStr[0]; if (registerResult == RR_Success) { SaveState(); } ForceDisconnect(); Config.RegisterResultCallback(registerResult); return; } } break; case CS_Logining: { Buffer += data.ToString(); string packetStr; if (Deserialize(Buffer, packetStr)) { packetStr = Decompress(packetStr); TServerLoginPacket packet; if (!packet.ParseFromString(packetStr)) { ForceDisconnect(); Config.LoginResultCallback(LR_ConnectionFail); return; } string captcha = packet.captcha(); State.set_serverpublickey(packet.publickey()); Config.CaptchaAvailableCallback(captcha); } } break; case CS_LoginingConfirmWait: { Buffer += data.ToString(); string packetStr; if (Deserialize(Buffer, packetStr)) { packetStr = Decompress(packetStr); TServerLoginConfirm packet; if (!packet.ParseFromString(packetStr)) { ForceDisconnect(); Config.LoginResultCallback(LR_ConnectionFail); return; } if (packet.result() != LR_Success) { ForceDisconnect(); Config.LoginResultCallback(packet.result()); } else { assert(packet.has_publickey() && "no public key in packet"); assert(packet.has_encryptedprivatekey() && "no private key in packet"); assert(!Password.empty() && "no password"); State.set_publickey(packet.publickey()); State.set_privatekey(DecryptSymmetrical(GenerateKey(Password), packet.encryptedprivatekey())); Password.clear(); SaveState(); ForceDisconnect(); Config.LoginResultCallback(packet.result()); } ForceDisconnect(); } } break; case CS_Connecting: { Buffer += data.ToString(); string packetStr; if (Deserialize(Buffer, packetStr)) { packetStr = Decompress(packetStr); TServerAuthorizeRequest packet; if (!packet.ParseFromString(packetStr)) { ForceDisconnect(); Config.ConnectedCallback(false); return; } if (!CheckSignature(State.serverpublickey(), packet.randomsequence(), packet.signature())) { ForceDisconnect(); Config.ConnectedCallback(false); return; } TClientAuthorizeRequest request; assert(State.has_login() && "no login in state"); request.set_login(State.login()); string hash = Hash(packet.randomsequence()); request.set_randomsequencehash(hash); request.set_randomsequencehashsignature(Sign(State.privatekey(), hash)); string response = Compress(request.SerializeAsString()); response = Serialize(EncryptAsymmetrical(State.serverpublickey(), response)); CurrentState = CS_ConnectingConfirmWait; UdtClient->Send(response); } } break; case CS_ConnectingConfirmWait: { Buffer += data.ToString(); string packetStr; if (Deserialize(Buffer, packetStr)) { assert(State.has_privatekey()); string sessionKey = Decompress(DecryptAsymmetrical(State.privatekey(), packetStr)); State.set_sessionkey(sessionKey); CurrentState = CS_Connected; Config.ConnectedCallback(true); string response; response.resize(1); response[0] = RT_SyncMessages; TSyncMessagesRequest syncRequest; if (State.has_lastsync()) { syncRequest.set_from(State.lastsync()); } else { syncRequest.set_from(0); } syncRequest.set_to(TDuration::Max().GetValue()); // request all messages after connection response += syncRequest.SerializeAsString(); response = EncryptSymmetrical(State.sessionkey(), Compress(response)); UdtClient->Send(Serialize(response)); } } break; case CS_Connected: { Buffer += data.ToString(); string packetStr; if (Deserialize(Buffer, packetStr)) { assert(!packetStr.empty() && "empty packet"); packetStr = DecryptSymmetrical(State.sessionkey(), packetStr); assert(!packetStr.empty() && "empty decrypted"); packetStr = Decompress(packetStr); assert(!packetStr.empty() && "empty decompress"); EServerPacket packetType = (EServerPacket)packetStr[0]; packetStr = packetStr.substr(1); switch (packetType) { case SP_FriendAlreadyExists: { // todo: just sync friendList if required // send repeated authorization request } break; case SP_FriendAdded: { // todo: send authorization request } break; case SP_SyncMessages: { TClientSyncPacket packet; if (!packet.ParseFromString(packetStr)) { throw UException("failed to parse client sync message packet"); } for (size_t i = 0; i < packet.encryptedmessages_size(); ++i) { const TDirectionedMessage& currMessage = packet.encryptedmessages(i); auto friendIt = Friends.find(currMessage.login()); if (friendIt == Friends.end()) { cerr << "warning: friend login not found\n"; continue; } TFriendRef& frnd = friendIt->second; frnd->OnOfflineMessageReceived(currMessage.message(), currMessage.incoming()); } State.set_lastsync(packet.to()); SaveState(); } break; case SP_SyncInfo: { TClientSyncInfoPacket packet; if (!packet.ParseFromString(packetStr)) { throw UException("failed to parse client sync info packet"); } for (TFriendIterator it = Friends.begin(); it != Friends.end(); ++it) { TFriendRef& frnd = it->second; frnd->ToDelete = true; } bool friendListUpdated = false; for (size_t i = 0; i < packet.friends_size(); ++i) { const TSyncFriend& frnd = packet.friends(i); auto frndIt = Friends.find(frnd.login()); TFriendRef currentFrnd; bool friendAdded = false; if (frndIt == Friends.end()) { // todo: refactor syncing friendListUpdated = true; friendAdded = true; Friends.insert(pair<string, TFriendRef>(frnd.login(), make_shared<TFriend>(this))); currentFrnd = Friends[frnd.login()]; currentFrnd->FullLogin = frnd.login(); currentFrnd->PublicKey = frnd.publickey(); currentFrnd->ServerPublicKey = frnd.serverpublickey(); currentFrnd->SelfOfflineKey = DecryptSymmetrical(GenerateKey(State.privatekey()), frnd.encryptedkey()); if (frnd.status() == AS_WaitingAuthorization) { currentFrnd->Status = FS_AddRequest; Config.FriendRequestCallback(frnd.login()); } else if (frnd.status() == AS_UnAuthorized) { currentFrnd->Status = FS_Unauthorized; } else if (frnd.status() == AS_Authorized) { currentFrnd->Status = FS_Offline; // todo: start trying to connect } else { assert(!"unknown status"); } } else { currentFrnd = frndIt->second; if (currentFrnd->PublicKey.empty()) { currentFrnd->PublicKey = frnd.publickey(); } else { if (currentFrnd->PublicKey != frnd.publickey()) { throw UException("public keys missmatch"); } } if (currentFrnd->SelfOfflineKey.empty()) { currentFrnd->SelfOfflineKey = DecryptSymmetrical(GenerateKey(State.privatekey()), frnd.encryptedkey()); } else { if (!frnd.encryptedkey().empty() && currentFrnd->SelfOfflineKey != DecryptSymmetrical(GenerateKey(State.privatekey()), frnd.encryptedkey())) { throw UException("public keys missmatch"); } } if (currentFrnd->ServerPublicKey.empty()) { currentFrnd->ServerPublicKey = frnd.serverpublickey(); } else { if (currentFrnd->ServerPublicKey != frnd.serverpublickey()) { throw UException("server public keys missmatch"); } } if ((currentFrnd->Status == FS_Unauthorized || currentFrnd->Status == FS_AddRequest) && frnd.status() == AS_Authorized) { friendListUpdated = true; currentFrnd->Status = FS_Offline; // todo: start trying to connect } else if (frnd.status() == AS_WaitingAuthorization) { currentFrnd->Status = FS_AddRequest; } else if (frnd.status() == AS_UnAuthorized) { currentFrnd->Status = FS_Unauthorized; } } if (currentFrnd->FriendOfflineKey.empty() && IsAuthorized(currentFrnd->Status)) { if (frnd.has_offlinekey() && frnd.has_offlinekeysignature()) { assert(!frnd.offlinekey().empty() && "empty offline key"); string offlineSignature = DecryptAsymmetrical(State.privatekey(), frnd.offlinekey()); assert(!currentFrnd->PublicKey.empty() && "no public key for friend"); if (!CheckSignature(currentFrnd->PublicKey, offlineSignature, frnd.offlinekeysignature())) { cerr << "all bad, wrong signature\n"; // todo: normal handling continue; } currentFrnd->FriendOfflineKey = DecryptAsymmetrical(State.privatekey(), frnd.offlinekey()); } } currentFrnd->ToDelete = false; if (friendAdded && Config.OnFriendAdded) { Config.OnFriendAdded(currentFrnd); } if (frnd.has_needofflinekey() && frnd.needofflinekey()) { string response; response.resize(1); response[0] = RT_SetFriendOfflineKey; TFriendOfflineKey offlineKeyPacket; assert(!currentFrnd->PublicKey.empty() && "missing friend public key"); assert(!currentFrnd->SelfOfflineKey.empty() && "missing self offline key for friend"); offlineKeyPacket.set_offlinekey(EncryptAsymmetrical(currentFrnd->PublicKey, currentFrnd->SelfOfflineKey)); offlineKeyPacket.set_offlinekeysignature(Sign(State.privatekey(), currentFrnd->SelfOfflineKey)); offlineKeyPacket.set_login(currentFrnd->GetLogin()); response += offlineKeyPacket.SerializeAsString(); response = EncryptSymmetrical(State.sessionkey(), Compress(response)); UdtClient->Send(Serialize(response)); } } for (TFriendIterator it = Friends.begin(); it != Friends.end();) { TFriendRef& frnd = it->second; if (frnd->ToDelete) { friendListUpdated = true; if (Config.OnFriendRemoved) { Config.OnFriendRemoved(frnd); } it = Friends.erase(it); } else { frnd->Connect(); ++it; } } if (friendListUpdated && Config.FriendlistChangedCallback) { Config.FriendlistChangedCallback(); } } break; case SP_ConnectToFriend: { auto frndIt = Friends.find(packetStr); if (frndIt == Friends.end()) { throw UException("no friend to connect to"); } TFriendRef& frnd = frndIt->second; frnd->ConnectAccept(); } } } } break; default: assert(false && "unknown state"); break; } }