/// <summary> /// Dequeues <see cref="QueuedRequest"/> from requests pool. /// </summary> /// <param name="requestId"><see cref="QueuedRequest"/> unique id.</param> /// <returns><see cref="QueuedRequest"/> if it was found in pool, otherwise <see cref="QueuedRequest.NotFound"/>.</returns> internal static QueuedRequest Dequeue(long requestId) { if (m_RequestsById.ContainsKey(requestId)) { QueuedRequest request = m_RequestsBySession[m_RequestsById[requestId]]; m_RequestsById.Remove(requestId); m_RequestsBySession.Remove(request.UserConnection.Session.ID); return(request); } return(QueuedRequest.NotFound); }
/// <summary> /// Dequeues <see cref="QueuedRequest"/> from requests pool. /// </summary> /// <param name="sessionID">Connection session unique id.</param> /// <returns><see cref="QueuedRequest"/> if it was found in pool, otherwise QueuedRequest.NotFound instance.</returns> internal static QueuedRequest Dequeue(int sessionID) { if (m_RequestsBySession.ContainsKey(sessionID)) { QueuedRequest request = m_RequestsBySession[sessionID]; m_RequestsBySession.Remove(sessionID); m_RequestsById.Remove(request.RequestID); return(request); } return(QueuedRequest.NotFound); }
/// <summary> /// Enqueues new <see cref="QueuedRequest"/> to requests pool. /// </summary> /// <param name="userConnection"><see cref="UserConnection"/> object to create request for.</param> /// <param name="requestId">Request unique id reference.</param> /// <returns>True, if request was added, otherwise false.</returns> internal static bool Enqueue( UserConnection userConnection, ref long requestId ) { if ( m_RequestsBySession.ContainsKey(userConnection.Session.ID) ) { #if DropUnAnsweredPackets m_RequestsBySession.Remove(userConnection.Session.ID); Logger.WriteLine(Source.InnerNetwork, "Previous request was dropped for session {0}", userConnection.Session.ToString()); #else Logger.WriteLine(Source.InnerNetwork, "Can't add new request for session {0}, there is other unanswered request.", userConnection.Session.ToString()); return false; #endif } QueuedRequest request = new QueuedRequest(NextRequestID(), userConnection); requestId = request.RequestID; m_RequestsBySession.Add(userConnection.Session.ID, request); m_RequestsById.Add(request.RequestID, userConnection.Session.ID); return true; }
/// <summary> /// Enqueues new <see cref="QueuedRequest"/> to requests pool. /// </summary> /// <param name="userConnection"><see cref="UserConnection"/> object to create request for.</param> /// <param name="requestId">Request unique id reference.</param> /// <returns>True, if request was added, otherwise false.</returns> internal static bool Enqueue(UserConnection userConnection, ref long requestId) { if (m_RequestsBySession.ContainsKey(userConnection.Session.ID)) { #if DropUnAnsweredPackets m_RequestsBySession.Remove(userConnection.Session.ID); Logger.WriteLine(Source.InnerNetwork, "Previous request was dropped for session {0}", userConnection.Session.ToString()); #else Logger.WriteLine(Source.InnerNetwork, "Can't add new request for session {0}, there is other unanswered request.", userConnection.Session.ToString()); return(false); #endif } QueuedRequest request = new QueuedRequest(NextRequestID(), userConnection); requestId = request.RequestID; m_RequestsBySession.Add(userConnection.Session.ID, request); m_RequestsById.Add(request.RequestID, userConnection.Session.ID); return(true); }
/// <summary> /// Validates provided <see cref="QueuedRequest"/>. /// </summary> /// <param name="request"><see cref="QueuedRequest"/> to validate.</param> /// <returns>True, if provided <see cref="QueuedRequest"/> is valid, otherwise false.</returns> internal static bool IsValid( QueuedRequest request ) { return request != QueuedRequest.NotFound && request.UserConnection != null && request.UserConnection.Connected; }
/// <summary> /// Handles incoming packet. /// </summary> /// <param name="p">Received <see cref="Packet"/> object.</param> internal static void Handle(Packet p) { switch (p.FirstOpcode) { case ServiceLayer.Identity: { switch (p.SecondOpcode) { case ServiceLayer.InitializeRequest: { return; // login service not handles incoming connections. } case ServiceLayer.InitializeResponse: // connection init response { InitializeResponse data = new InitializeResponse(p); switch (data.Answer) { case InitializeResponse.Accepted: { CacheServiceConnection.Connection.SetRemoteService(data.RemoteServiceID, ( ServiceType )data.RemoteServiceType); Logger.WriteLine(Source.InnerNetwork, "Authorized on {0} (0x{1})", CacheServiceConnection.Connection.ServiceType, CacheServiceConnection.Connection.ServiceID.ToString("x2")); // send set-settings request CacheServiceConnection.Send ( new SetSettingsRequest().ToPacket ( new LoginServiceSettings ( Settings.Default.ServiceUniqueID, Settings.Default.LoginServiceAutoCreateUsers, Settings.Default.LoginServiceDefaultAccessLevel ) ) ); return; } case InitializeResponse.Rejected: { Logger.WriteLine(Source.InnerNetwork, "Connection rejected by {0} (0x{1})", ( ServiceType )data.RemoteServiceType, data.RemoteServiceID); return; } } return; } case ServiceLayer.SetSettingsRequest: { return; // login service not handles remote service settings request } case ServiceLayer.SetSettingsResponse: { SetSettingsResponse response = new SetSettingsResponse(p); switch (response.Response) { case SetSettingsResponse.Accepted: { Logger.WriteLine(Source.InnerNetwork, "Cache service accepted service settings."); //UserConnectionsListener.Enable(); // start listen incoming user connections return; } default: { Service.Terminate(new ServiceShutdownEventArgs("Cache service rejected settings setup.")); return; } } } default: { Logger.WriteLine("Unknown packet received on layer 0x{0}: {1}", ServiceLayer.Identity.ToString("x2"), p.ToString()); return; } } } case UserDataLayer.Identity: { switch (p.SecondOpcode) { case UserDataLayer.UserAuthenticationResponse: { UserAuthenticationResponse response = new UserAuthenticationResponse(p); QueuedRequest request = QueuedRequestsPool.Dequeue(response.RequestID); if (QueuedRequest.IsValid(request)) { switch (response.Response) { case UserAuthenticationResponseType.UserAccepted: // accepted or created by cache { request.UserConnection.Session.AccountID = response.UserID; request.UserConnection.Session.LastWorld = response.LastWorldID; if (response.AccessLevel < Settings.Default.LoginServiceAllowedAccessLevel) { request.Send(LoginFailed.ToPacket(UserAuthenticationResponseType.AccessFailed)); UserConnectionsListener.CloseActiveConnection(request.UserConnection); return; } long requestId = long.MinValue; if (QueuedRequestsPool.Enqueue(request.UserConnection, ref requestId)) { CacheServiceConnection.Send ( new CacheUserSessionRequest ( requestId, request.UserConnection.Session ).ToPacket() ); } else { Logger.WriteLine(Source.InnerNetwork, "Failed to send CacheUserSessionRequest to cache service, request was not enqueued by QueuedRequestsPool ?..."); UserConnectionsListener.CloseActiveConnection(request.UserConnection); } return; } default: { request.Send(LoginFailed.ToPacket(response.Response)); UserConnectionsListener.CloseActiveConnection(request.UserConnection); return; } } } break; } case UserDataLayer.CacheUserSessionResponse: { CacheUserSessionResponse response = new CacheUserSessionResponse(p); QueuedRequest request = QueuedRequestsPool.Dequeue(response.RequestID); if (QueuedRequest.IsValid(request)) { switch (response.Response) { case CacheUserSessionResponse.Failed: { Logger.WriteLine("Failed to cache user session data on cache server side"); request.Send(LoginFailed.ToPacket(UserAuthenticationResponseType.SystemError)); UserConnectionsListener.CloseActiveConnection(request.UserConnection); return; } case CacheUserSessionResponse.Accepted: { request.Send(LoginOk.ToPacket(request.UserConnection.Session)); return; } } } else { Logger.WriteLine(Source.OuterNetwork, "Failed to send ServerPackets.WorldsList to client, request was not dequeued by QueuedRequestsPool ?..."); UserConnectionsListener.CloseActiveConnection(request.UserConnection); } return; } case UserDataLayer.WorldsListResponse: { WorldsListResponse response = new WorldsListResponse(p); QueuedRequest request = QueuedRequestsPool.Dequeue(response.RequestID); if (QueuedRequest.IsValid(request)) { request.Send(ServerList.ToPacket(request.UserConnection.Session.LastWorld, response.Data)); } else { Logger.WriteLine(Source.OuterNetwork, "Failed to send ServerPackets.WorldsList to client, request was not dequeued by QueuedRequestsPool ?..."); UserConnectionsListener.CloseActiveConnection(request.UserConnection); } return; } case UserDataLayer.JoinWorldResponse: { JoinWorldResponse response = new JoinWorldResponse(p); QueuedRequest request = QueuedRequestsPool.Dequeue(response.RequestID); if (QueuedRequest.IsValid(request)) { switch (response.Result) { case JoinWorldRequestResult.Accepted: { request.UserConnection.Send(PlayAccepted.ToPacket(request.UserConnection.Session)); break; } default: { request.UserConnection.Send(PlayFail.ToPacket(response.Result)); break; } } } UserConnectionsListener.CloseConnectionWithoutLogout(request.UserConnection); return; } } break; } } Logger.WriteLine("Unknown packet received from {0} service on layer 0x{1}:{2}{3}", ServiceType.LoginService, p.FirstOpcode.ToString("x2"), Environment.NewLine, p.ToString()); }
/// <summary> /// Validates provided <see cref="QueuedRequest"/>. /// </summary> /// <param name="request"><see cref="QueuedRequest"/> to validate.</param> /// <returns>True, if provided <see cref="QueuedRequest"/> is valid, otherwise false.</returns> internal static bool IsValid(QueuedRequest request) { return(request != QueuedRequest.NotFound && request.UserConnection != null && request.UserConnection.Connected); }