/// <summary> /// Określa jaka odpowiedź ma być zwrócona do klienta w przypadku nieudanej autoryzacji /// </summary> /// <returns>Obiekt JSON do przekazania do klienta</returns> protected virtual JObject GetAuthorizationResponseFailed() { var resp = new StandardResponseSerializer() { Status = "FORBIDDEN", Message = "Authorization failed" }; return(resp.GetApiObject()); }
/// <summary> /// Określa jaka odpowiedź ma być zwrócona do klienta w przypadku udanej autoryzacji /// </summary> /// <returns>Obiekt JSON do przekazania do klienta</returns> protected virtual JObject GetAuthorizationResponseSuccessful() { var resp = new StandardResponseSerializer() { Status = "OK", Message = "Authorization successful" }; return(resp.GetApiObject()); }
/// <summary> /// Treść komunikatu przy odłączeniu klienta od serwera przez zbyt długi czas autoryzacji /// </summary> /// <returns>Obiekt JSON do przekazania do klienta</returns> protected virtual JObject GetAuthorizationTimeoutSignal() { var resp = new StandardResponseSerializer() { Status = "AUTHORIZATION_TIMEOUT", Message = "Authorization failed - timeout" }; var result = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_AUTHORIZATION, Data = resp.GetApiObject() }; return(result.GetApiObject()); }
/// <summary> /// Treść komunikatu przy odłączeniu klienta od serwera /// </summary> /// <returns>Obiekt JSON do przekazania do klienta</returns> protected virtual JObject GetDisconnectedSignal() { var resp = new StandardResponseSerializer() { Status = "DISCONNECTED", Message = "You have been disconnected" }; var result = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_SERVER_SIGNAL, Data = resp.GetApiObject() }; return(result.GetApiObject()); }
private void Listen() { TcpListener = new TcpListener(IpAddress, Port); TcpListener.Start(); List <ClientConnection> toRemove = new List <ClientConnection>(); List <ClientConnection> currentlyAuthorized = new List <ClientConnection>(); while (true) { // Komunikaty toRemove.Clear(); foreach (var connection in AuthorizedConnections) { try { connection.SendCommunicates(); } catch (IOException) { toRemove.Add(connection); } catch (ObjectDisposedException) { toRemove.Add(connection); } catch (InvalidOperationException) { toRemove.Add(connection); } catch (Exception) { Console.WriteLine("Nie można było wysłać komunikatów do klienta: " + connection.ToString()); } } // Usuwanie zamkniętych połączeń foreach (var connection in toRemove) { connection.Dispose(); AuthorizedConnections.Remove(connection); } toRemove.Clear(); foreach (var connection in UnauthorizedConnections) { try { connection.SendCommunicates(); } catch (IOException) { toRemove.Add(connection); } catch (ObjectDisposedException) { toRemove.Add(connection); } catch (InvalidOperationException) { toRemove.Add(connection); } catch (Exception) { Console.WriteLine("Nie można było wysłać komunikatów do klienta: " + connection.ToString()); } } // Usuwanie zamkniętych połączeń foreach (var connection in toRemove) { connection.Dispose(); UnauthorizedConnections.Remove(connection); } // Zautoryzowane połączenia bool canContinue; toRemove.Clear(); foreach (var connection in AuthorizedConnections) { if (connection.DataAvailable) { connection.LastActivateAt = DateTime.Now; JObject data = connection.GetData(); JObject response; canContinue = true; // Inicjalna walidacja (Bierzemy kod zapytania, jeśli został podany) var initialCheck = new StandardRequestSerializer(data); try { initialCheck.Validate(); } catch (ValidationException) { // Inicjalny format nie przechodzi sprawdzenia var result = new StandardCommunicateSerializer(); var resp = new StandardResponseSerializer(); result.CommunicateType = StandardCommunicateSerializer.TYPE_REQUEST_ERROR; resp.Status = "INVALID_FORMAT"; resp.Message = "Request failed initial validation"; result.Data = resp.GetApiObject(); response = result.GetApiObject(); connection.WriteData(response); connection.Flush(); canContinue = false; } if (canContinue) { try { try { var resp = HandleRequest(connection, initialCheck.Data); var respWrapper = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_RESPONSE, RequestCode = initialCheck.RequestCode, Data = resp }; response = respWrapper.GetApiObject(); } catch (ValidationException e) { var resp = e.GetJson(); var respWrapper = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_RESPONSE, RequestCode = initialCheck.RequestCode, Data = resp }; response = respWrapper.GetApiObject(); } } catch (Exception e) { var resp = new StandardResponseSerializer() { Status = "ERR_INTERNAL", Message = "Wystąpił wewnętrzny błąd serwera" }; var respWrapper = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_REQUEST_ERROR, RequestCode = initialCheck.RequestCode, Data = resp.GetApiObject() }; response = respWrapper.GetApiObject(); } try { connection.WriteData(response); connection.Flush(); } catch (IOException) { toRemove.Add(connection); } catch (InvalidOperationException) { toRemove.Add(connection); } } } else if (TimeSpan.Compare(DateTime.Now - connection.LastActivateAt, MaxIdleTime) > 0) { Console.WriteLine("IDLE CHECK"); connection.LastActivateAt = DateTime.Now; var wrappedResponse = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_CONNECTION_CHECK, RequestCode = -1, Data = null }; try { connection.WriteData(wrappedResponse.GetApiObject()); } catch (IOException) { toRemove.Add(connection); } catch (ObjectDisposedException) { toRemove.Add(connection); } catch (InvalidOperationException) { toRemove.Add(connection); } catch (Exception) { Console.WriteLine("Nie można było wysłać komunikatów do klienta: " + connection.ToString()); } } } // Usuwanie zamkniętych połączeń foreach (var connection in toRemove) { connection.Dispose(); AuthorizedConnections.Remove(connection); } // Niezautoryzowane połączenia toRemove.Clear(); foreach (var connection in UnauthorizedConnections) { bool authorized = false; if (connection.DataAvailable) { canContinue = true; JObject data = connection.GetData(); var initialCheck = new StandardRequestSerializer(data); try { try { initialCheck.Validate(); } catch (ValidationException e) { var wrappedResponse = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_AUTHORIZATION, RequestCode = initialCheck.RequestCode, Data = GetAuthorizationResponseFailed() }; connection.WriteData(wrappedResponse.GetApiObject()); connection.Flush(); canContinue = false; } if (canContinue) { // Zero zaufania do niezautoryzowanych połączeń try { if (AuthorizeConnection(connection, initialCheck.Data)) { var response = GetAuthorizationResponseSuccessful(); var wrappedResponse = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_AUTHORIZATION, RequestCode = initialCheck.RequestCode, Data = response }; authorized = true; // Informacja dla odbiorcy o poprawnej autoryzacji connection.WriteData(wrappedResponse.GetApiObject()); connection.Flush(); connection.LastActivateAt = DateTime.Now; currentlyAuthorized.Add(connection); } else { var response = GetAuthorizationResponseFailed(); var wrappedResponse = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_AUTHORIZATION, RequestCode = initialCheck.RequestCode, Data = response }; connection.WriteData(wrappedResponse.GetApiObject()); connection.Flush(); } } catch (ValidationException e) { var wrappedResponse = new StandardCommunicateSerializer() { CommunicateType = StandardCommunicateSerializer.TYPE_AUTHORIZATION, RequestCode = initialCheck.RequestCode, Data = GetAuthorizationResponseFailed() }; connection.WriteData(wrappedResponse.GetApiObject()); connection.Flush(); } } } catch (IOException e) { // Połączenie socketu rozłączone toRemove.Add(connection); } catch (ObjectDisposedException e) { // Połączenie socketu rozłączone toRemove.Add(connection); } catch (InvalidOperationException) { toRemove.Add(connection); } catch (Exception e) { Console.WriteLine("Nieobsłużony wyjątek dla zapytania od połączenia " + connection.ToString() + "\n" + e.ToString()); } } if (!authorized && TimeSpan.Compare(connection.GetConnectionTime(), TimeForAuthorization) > 0) { connection.WriteData(GetAuthorizationTimeoutSignal()); connection.Flush(); connection.TcpClient.Close(); toRemove.Add(connection); } } // Finalizacja przenoszenie połączenia po zautoryzowaniu lub zamknięciu foreach (var connection in currentlyAuthorized) { UnauthorizedConnections.Remove(connection); AuthorizedConnections.Add(connection); } currentlyAuthorized.Clear(); foreach (var connection in toRemove) { connection.Dispose(); UnauthorizedConnections.Remove(connection); } // Odłączanie klientów do odłączenia foreach (var connection in ClientsToDisconnect) { if (AuthorizedConnections.Contains(connection)) { try { connection.WriteData(GetDisconnectedSignal()); connection.Flush(); } catch (Exception) { } connection.Dispose(); AuthorizedConnections.Remove(connection); } else if (UnauthorizedConnections.Contains(connection)) { try { connection.WriteData(GetDisconnectedSignal()); connection.Flush(); } catch (Exception) { } connection.Dispose(); UnauthorizedConnections.Remove(connection); } } // Nowe połączenia HandleIncommingConnections(); } }