Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
//--------------------------------------------------------------------------
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();
}
Пример #4
0
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;
    }
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
    }
}