From 5c5afc003bed782489ba46d61fff433cf2e9c556 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Fri, 13 Dec 2024 14:20:35 +0200 Subject: [PATCH] complete lab4 again --- .../ChatRoomContract/Protos/service.proto | 61 -- .../ChatRoomContract/NswagChatRoomClient.cs | 966 ------------------ Lab2-rest/ChatRoomContract/nswag.json | 19 - Lab4/.vscode/launch.json | 76 +- Lab4/.vscode/tasks.json | 62 +- Lab4/ChatRoom/ChatRoomRabbitMQService.cs | 159 --- Lab4/ChatRoom/Server.cs | 197 ---- Lab4/ChatRoomContract/ChatRoomContract.csproj | 19 +- Lab4/ChatRoomContract/ChatRoomGrpcClient.cs | 116 --- .../ChatRoomRabbitMQClient.cs | 243 ----- Lab4/ChatRoomContract/ChatRoomRestClient.cs | 124 --- .../ChatRoomContract/GrpcChatRoomClient.cs | 4 +- ...hatRoomContract.cs => IChatRoomService.cs} | 7 +- Lab4/ChatRoomContract/NswagChatRoomClient.cs | 26 +- Lab4/ChatRoomContract/RPCMessage.cs | 49 - Lab4/ChatRoomContract/RabbitMQConfig.cs | 30 - .../ChatRoomContract/RestChatRoomClient.cs | 4 +- Lab4/ChatRoomContract/nswag.json | 2 +- .../ChatRoomLogic.cs | 3 +- .../ChatRoomService.cs} | 13 +- .../ChatRoomSimpleRPC.csproj} | 7 +- .../ChatRoomState.cs | 0 .../Properties/launchSettings.json | 0 Lab4/ChatRoomSimpleRPC/Server.cs | 100 ++ .../appsettings.json | 0 .../ChatRoomService.cs} | 27 +- .../GrpcToSimpleRPCAdapter.csproj} | 7 +- .../Properties/launchSettings.json | 12 + Lab4/GrpcToSimpleRPCAdapter/Server.cs | 122 +++ Lab4/GrpcToSimpleRPCAdapter/appsettings.json | 11 + Lab4/Lab4.sln | 98 +- Lab4/Moderator/Moderator.csproj | 18 - Lab4/Moderator/ModeratorLogic.cs | 49 - Lab4/ModeratorGrpc/Moderator.cs | 52 - Lab4/ModeratorGrpc/ModeratorGrpc.csproj | 19 - Lab4/ModeratorRabbitMQ/Moderator.cs | 61 -- .../ModeratorRabbitMQ.csproj | 19 - Lab4/ModeratorRest/Moderator.cs | 54 +- Lab4/ModeratorRest/ModeratorRest.csproj | 2 +- Lab4/ModeratorSimpleRPC/Moderator.cs | 81 -- Lab4/Participant/Participant.csproj | 18 - Lab4/Participant/ParticipantLogic.cs | 54 - Lab4/ParticipantGrpc/Participant.cs | 60 +- Lab4/ParticipantGrpc/ParticipantGrpc.csproj | 2 +- Lab4/ParticipantRabbitMQ/Participant.cs | 60 -- .../ParticipantRabbitMQ.csproj | 19 - Lab4/ParticipantRest/Participant.cs | 52 - Lab4/ParticipantRest/ParticipantRest.csproj | 19 - Lab4/ParticipantSimpleRPC/Participant.cs | 81 -- .../ChatRoomController.cs} | 25 +- .../Properties/launchSettings.json | 12 + .../RestToSimpleRPCAdapter.csproj} | 4 +- Lab4/RestToSimpleRPCAdapter/Server.cs | 147 +++ Lab4/RestToSimpleRPCAdapter/appsettings.json | 11 + 54 files changed, 631 insertions(+), 2852 deletions(-) delete mode 100644 Lab2-grpc/ChatRoomContract/Protos/service.proto delete mode 100644 Lab2-rest/ChatRoomContract/NswagChatRoomClient.cs delete mode 100644 Lab2-rest/ChatRoomContract/nswag.json delete mode 100644 Lab4/ChatRoom/ChatRoomRabbitMQService.cs delete mode 100644 Lab4/ChatRoom/Server.cs delete mode 100644 Lab4/ChatRoomContract/ChatRoomGrpcClient.cs delete mode 100644 Lab4/ChatRoomContract/ChatRoomRabbitMQClient.cs delete mode 100644 Lab4/ChatRoomContract/ChatRoomRestClient.cs rename Lab2-grpc/ChatRoomContract/ChatRoomClient.cs => Lab4/ChatRoomContract/GrpcChatRoomClient.cs (97%) rename Lab4/ChatRoomContract/{IChatRoomContract.cs => IChatRoomService.cs} (95%) delete mode 100644 Lab4/ChatRoomContract/RPCMessage.cs delete mode 100644 Lab4/ChatRoomContract/RabbitMQConfig.cs rename Lab2-rest/ChatRoomContract/ChatRoomClient.cs => Lab4/ChatRoomContract/RestChatRoomClient.cs (96%) rename Lab4/{ChatRoom => ChatRoomSimpleRPC}/ChatRoomLogic.cs (99%) rename Lab4/{ChatRoom/ChatRoomSimpleRPCService.cs => ChatRoomSimpleRPC/ChatRoomService.cs} (75%) rename Lab4/{ModeratorSimpleRPC/ModeratorSimpleRPC.csproj => ChatRoomSimpleRPC/ChatRoomSimpleRPC.csproj} (70%) rename Lab4/{ChatRoom => ChatRoomSimpleRPC}/ChatRoomState.cs (100%) rename Lab4/{ChatRoom => ChatRoomSimpleRPC}/Properties/launchSettings.json (100%) create mode 100644 Lab4/ChatRoomSimpleRPC/Server.cs rename Lab4/{ChatRoom => ChatRoomSimpleRPC}/appsettings.json (100%) rename Lab4/{ChatRoom/ChatRoomGrpcService.cs => GrpcToSimpleRPCAdapter/ChatRoomService.cs} (80%) rename Lab4/{ParticipantSimpleRPC/ParticipantSimpleRPC.csproj => GrpcToSimpleRPCAdapter/GrpcToSimpleRPCAdapter.csproj} (69%) create mode 100644 Lab4/GrpcToSimpleRPCAdapter/Properties/launchSettings.json create mode 100644 Lab4/GrpcToSimpleRPCAdapter/Server.cs create mode 100644 Lab4/GrpcToSimpleRPCAdapter/appsettings.json delete mode 100644 Lab4/Moderator/Moderator.csproj delete mode 100644 Lab4/Moderator/ModeratorLogic.cs delete mode 100644 Lab4/ModeratorGrpc/Moderator.cs delete mode 100644 Lab4/ModeratorGrpc/ModeratorGrpc.csproj delete mode 100644 Lab4/ModeratorRabbitMQ/Moderator.cs delete mode 100644 Lab4/ModeratorRabbitMQ/ModeratorRabbitMQ.csproj delete mode 100644 Lab4/ModeratorSimpleRPC/Moderator.cs delete mode 100644 Lab4/Participant/Participant.csproj delete mode 100644 Lab4/Participant/ParticipantLogic.cs delete mode 100644 Lab4/ParticipantRabbitMQ/Participant.cs delete mode 100644 Lab4/ParticipantRabbitMQ/ParticipantRabbitMQ.csproj delete mode 100644 Lab4/ParticipantRest/Participant.cs delete mode 100644 Lab4/ParticipantRest/ParticipantRest.csproj delete mode 100644 Lab4/ParticipantSimpleRPC/Participant.cs rename Lab4/{ChatRoom/ChatRoomRestController.cs => RestToSimpleRPCAdapter/ChatRoomController.cs} (82%) create mode 100644 Lab4/RestToSimpleRPCAdapter/Properties/launchSettings.json rename Lab4/{ChatRoom/ChatRoom.csproj => RestToSimpleRPCAdapter/RestToSimpleRPCAdapter.csproj} (81%) create mode 100644 Lab4/RestToSimpleRPCAdapter/Server.cs create mode 100644 Lab4/RestToSimpleRPCAdapter/appsettings.json diff --git a/Lab2-grpc/ChatRoomContract/Protos/service.proto b/Lab2-grpc/ChatRoomContract/Protos/service.proto deleted file mode 100644 index 66c05f8..0000000 --- a/Lab2-grpc/ChatRoomContract/Protos/service.proto +++ /dev/null @@ -1,61 +0,0 @@ -//set the language version -syntax = "proto3"; - -//this will translate into C# namespace -package ChatRoomContract.Protocol; - -import "google/protobuf/empty.proto"; -import "google/protobuf/timestamp.proto"; - -service ChatRoom { - rpc RegisterClient(RegisterClientRequest) returns (ClientId); - rpc GetStrikes(ClientId) returns (Srikes); - rpc GetBlockedUntil(ClientId) returns (BlockedUntil); - rpc SendMessage(UserMessageRequest) returns (BoolResponse); - rpc GetNewMessage(google.protobuf.Empty) returns (NewUserMessage); - rpc RejectMessage(MessageId) returns (google.protobuf.Empty); - rpc ApproveMessage(MessageId) returns (google.protobuf.Empty); -} - -message BoolResponse { - bool success = 1; -} - -message RegisterClientRequest { - string name = 1; -} - -message Srikes { - int32 strikes = 1; -} - -message ClientId { - int32 id = 1; -} - -message MessageId { - int32 id = 1; -} - -message BlockedUntil { - bool hasTimestamp = 1; - google.protobuf.Timestamp timestamp = 2; -} - -message UserMessageRequest { - int32 clientId = 1; - string contents = 2; - bool needsToBeCensored = 3; -} - - -message UserMessage { - int32 id = 1; - string contents = 2; - bool needsToBeCensored = 3; -} - -message NewUserMessage { - bool hasMessage = 1; - UserMessage message = 2; -} \ No newline at end of file diff --git a/Lab2-rest/ChatRoomContract/NswagChatRoomClient.cs b/Lab2-rest/ChatRoomContract/NswagChatRoomClient.cs deleted file mode 100644 index 5bebd74..0000000 --- a/Lab2-rest/ChatRoomContract/NswagChatRoomClient.cs +++ /dev/null @@ -1,966 +0,0 @@ -//---------------------- -// -// Generated using the NSwag toolchain v14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) -// -//---------------------- - -#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." -#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." -#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' -#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" -#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" -#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... -#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." -#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" -#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" -#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" -#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" -#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" -#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." - -namespace NswagGenerated -{ - using System = global::System; - - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class NswagChatRoomClient - { - #pragma warning disable 8618 - private string _baseUrl; - #pragma warning restore 8618 - - private System.Net.Http.HttpClient _httpClient; - private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); - private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; - - #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public NswagChatRoomClient(string baseUrl, System.Net.Http.HttpClient httpClient) - #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - { - BaseUrl = baseUrl; - _httpClient = httpClient; - Initialize(); - } - - private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() - { - var settings = new Newtonsoft.Json.JsonSerializerSettings(); - UpdateJsonSerializerSettings(settings); - return settings; - } - - public string BaseUrl - { - get { return _baseUrl; } - set - { - _baseUrl = value; - if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) - _baseUrl += '/'; - } - } - - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } - - static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); - - partial void Initialize(); - - partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); - partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); - partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); - - /// - /// Register client with a name - /// - /// Name of client, can be duplicate between clients - /// Success - /// A server side error occurred. - public virtual System.Threading.Tasks.Task RegisterClientAsync(string name) - { - return RegisterClientAsync(name, System.Threading.CancellationToken.None); - } - - /// - /// Register client with a name - /// - /// Name of client, can be duplicate between clients - /// Success - /// A server side error occurred. - public virtual int RegisterClient(string name) - { - return System.Threading.Tasks.Task.Run(async () => await RegisterClientAsync(name, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - /// Register client with a name - /// - /// Name of client, can be duplicate between clients - /// Success - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task RegisterClientAsync(string name, System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "text/plain"); - request_.Method = new System.Net.Http.HttpMethod("POST"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "registerClient" - urlBuilder_.Append("registerClient"); - urlBuilder_.Append('?'); - if (name != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("name")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(name, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - /// - /// Get number of strikes a participant has - /// - /// Client ID - /// Success - /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetStrikesAsync(int? clientId) - { - return GetStrikesAsync(clientId, System.Threading.CancellationToken.None); - } - - /// - /// Get number of strikes a participant has - /// - /// Client ID - /// Success - /// A server side error occurred. - public virtual int GetStrikes(int? clientId) - { - return System.Threading.Tasks.Task.Run(async () => await GetStrikesAsync(clientId, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - /// Get number of strikes a participant has - /// - /// Client ID - /// Success - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetStrikesAsync(int? clientId, System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "getStrikes" - urlBuilder_.Append("getStrikes"); - urlBuilder_.Append('?'); - if (clientId != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("clientId")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(clientId, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - /// - /// Get timestamp until when the client is blocked - /// - /// Client ID - /// Success - /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetBlockedUntilAsync(int? clientId) - { - return GetBlockedUntilAsync(clientId, System.Threading.CancellationToken.None); - } - - /// - /// Get timestamp until when the client is blocked - /// - /// Client ID - /// Success - /// A server side error occurred. - public virtual System.DateTimeOffset GetBlockedUntil(int? clientId) - { - return System.Threading.Tasks.Task.Run(async () => await GetBlockedUntilAsync(clientId, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - /// Get timestamp until when the client is blocked - /// - /// Client ID - /// Success - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetBlockedUntilAsync(int? clientId, System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "getBlockedUntil" - urlBuilder_.Append("getBlockedUntil"); - urlBuilder_.Append('?'); - if (clientId != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("clientId")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(clientId, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - /// - /// Send a message, will be given to a moderator to be approved - /// - /// Client ID - /// Message contents - /// Does this message need to be censored? - /// Success - /// A server side error occurred. - public virtual System.Threading.Tasks.Task SendMessageAsync(int? clientId, string contents, bool? needsToBeCensored) - { - return SendMessageAsync(clientId, contents, needsToBeCensored, System.Threading.CancellationToken.None); - } - - /// - /// Send a message, will be given to a moderator to be approved - /// - /// Client ID - /// Message contents - /// Does this message need to be censored? - /// Success - /// A server side error occurred. - public virtual bool SendMessage(int? clientId, string contents, bool? needsToBeCensored) - { - return System.Threading.Tasks.Task.Run(async () => await SendMessageAsync(clientId, contents, needsToBeCensored, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - /// Send a message, will be given to a moderator to be approved - /// - /// Client ID - /// Message contents - /// Does this message need to be censored? - /// Success - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task SendMessageAsync(int? clientId, string contents, bool? needsToBeCensored, System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "text/plain"); - request_.Method = new System.Net.Http.HttpMethod("POST"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "sendMessage" - urlBuilder_.Append("sendMessage"); - urlBuilder_.Append('?'); - if (clientId != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("clientId")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(clientId, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - if (contents != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("contents")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(contents, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - if (needsToBeCensored != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("needsToBeCensored")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(needsToBeCensored, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - /// - /// Get the next message which hasn't been approved or rejected - /// - /// Success - /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetNewMessageAsync() - { - return GetNewMessageAsync(System.Threading.CancellationToken.None); - } - - /// - /// Get the next message which hasn't been approved or rejected - /// - /// Success - /// A server side error occurred. - public virtual Message GetNewMessage() - { - return System.Threading.Tasks.Task.Run(async () => await GetNewMessageAsync(System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - /// Get the next message which hasn't been approved or rejected - /// - /// Success - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetNewMessageAsync(System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "getNewMessage" - urlBuilder_.Append("getNewMessage"); - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - /// - /// Reject a message - /// - /// Message ID - /// Success - /// A server side error occurred. - public virtual System.Threading.Tasks.Task RejectMessageAsync(int? messageId) - { - return RejectMessageAsync(messageId, System.Threading.CancellationToken.None); - } - - /// - /// Reject a message - /// - /// Message ID - /// Success - /// A server side error occurred. - public virtual void RejectMessage(int? messageId) - { - System.Threading.Tasks.Task.Run(async () => await RejectMessageAsync(messageId, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - /// Reject a message - /// - /// Message ID - /// Success - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task RejectMessageAsync(int? messageId, System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json"); - request_.Method = new System.Net.Http.HttpMethod("POST"); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "rejectMessage" - urlBuilder_.Append("rejectMessage"); - urlBuilder_.Append('?'); - if (messageId != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("messageId")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(messageId, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - return; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - /// - /// Approve a message - /// - /// Message ID - /// Success - /// A server side error occurred. - public virtual System.Threading.Tasks.Task ApproveMessageAsync(int? messageId) - { - return ApproveMessageAsync(messageId, System.Threading.CancellationToken.None); - } - - /// - /// Approve a message - /// - /// Message ID - /// Success - /// A server side error occurred. - public virtual void ApproveMessage(int? messageId) - { - System.Threading.Tasks.Task.Run(async () => await ApproveMessageAsync(messageId, System.Threading.CancellationToken.None)).GetAwaiter().GetResult(); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// - /// Approve a message - /// - /// Message ID - /// Success - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ApproveMessageAsync(int? messageId, System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json"); - request_.Method = new System.Net.Http.HttpMethod("POST"); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "approveMessage" - urlBuilder_.Append("approveMessage"); - urlBuilder_.Append('?'); - if (messageId != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("messageId")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(messageId, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - return; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - protected struct ObjectResponseResult - { - public ObjectResponseResult(T responseObject, string responseText) - { - this.Object = responseObject; - this.Text = responseText; - } - - public T Object { get; } - - public string Text { get; } - } - - public bool ReadResponseAsString { get; set; } - - protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Threading.CancellationToken cancellationToken) - { - if (response == null || response.Content == null) - { - return new ObjectResponseResult(default(T), string.Empty); - } - - if (ReadResponseAsString) - { - var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - try - { - var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings); - return new ObjectResponseResult(typedBody, responseText); - } - catch (Newtonsoft.Json.JsonException exception) - { - var message = "Could not deserialize the response body string as " + typeof(T).FullName + "."; - throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception); - } - } - else - { - try - { - using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - using (var streamReader = new System.IO.StreamReader(responseStream)) - using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) - { - var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings); - var typedBody = serializer.Deserialize(jsonTextReader); - return new ObjectResponseResult(typedBody, string.Empty); - } - } - catch (Newtonsoft.Json.JsonException exception) - { - var message = "Could not deserialize the response body stream as " + typeof(T).FullName + "."; - throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception); - } - } - } - - private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) - { - if (value == null) - { - return ""; - } - - if (value is System.Enum) - { - var name = System.Enum.GetName(value.GetType(), value); - if (name != null) - { - var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); - if (field != null) - { - var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) - as System.Runtime.Serialization.EnumMemberAttribute; - if (attribute != null) - { - return attribute.Value != null ? attribute.Value : name; - } - } - - var converted = System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo)); - return converted == null ? string.Empty : converted; - } - } - else if (value is bool) - { - return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); - } - else if (value is byte[]) - { - return System.Convert.ToBase64String((byte[]) value); - } - else if (value is string[]) - { - return string.Join(",", (string[])value); - } - else if (value.GetType().IsArray) - { - var valueArray = (System.Array)value; - var valueTextArray = new string[valueArray.Length]; - for (var i = 0; i < valueArray.Length; i++) - { - valueTextArray[i] = ConvertToString(valueArray.GetValue(i), cultureInfo); - } - return string.Join(",", valueTextArray); - } - - var result = System.Convert.ToString(value, cultureInfo); - return result == null ? "" : result; - } - } - - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class Message - { - [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public int Id { get; set; } - - [Newtonsoft.Json.JsonProperty("contents", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Contents { get; set; } - - [Newtonsoft.Json.JsonProperty("needsToBeCensored", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public bool NeedsToBeCensored { get; set; } - - } - - - - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class ApiException : System.Exception - { - public int StatusCode { get; private set; } - - public string Response { get; private set; } - - public System.Collections.Generic.IReadOnlyDictionary> Headers { get; private set; } - - public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Exception innerException) - : base(message + "\n\nStatus: " + statusCode + "\nResponse: \n" + ((response == null) ? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)), innerException) - { - StatusCode = statusCode; - Response = response; - Headers = headers; - } - - public override string ToString() - { - return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString()); - } - } - - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class ApiException : ApiException - { - public TResult Result { get; private set; } - - public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, TResult result, System.Exception innerException) - : base(message, statusCode, response, headers, innerException) - { - Result = result; - } - } - -} - -#pragma warning restore 108 -#pragma warning restore 114 -#pragma warning restore 472 -#pragma warning restore 612 -#pragma warning restore 1573 -#pragma warning restore 1591 -#pragma warning restore 8073 -#pragma warning restore 3016 -#pragma warning restore 8603 -#pragma warning restore 8604 -#pragma warning restore 8625 \ No newline at end of file diff --git a/Lab2-rest/ChatRoomContract/nswag.json b/Lab2-rest/ChatRoomContract/nswag.json deleted file mode 100644 index 1f4e5a1..0000000 --- a/Lab2-rest/ChatRoomContract/nswag.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "runtime": "Net60", - "documentGenerator": { - "fromDocument": { - "url": "http://localhost:5000/swagger/v1/swagger.json", - "output": null - } - }, - - "codeGenerators": { - "openApiToCSharpClient": { - "classname" : "NswagChatRoomClient", - "namespace" : "NswagGenerated", - "output" : "NswagChatRoomClient.cs", - - "generateSyncMethods": true - } - } -} \ No newline at end of file diff --git a/Lab4/.vscode/launch.json b/Lab4/.vscode/launch.json index c84acf9..499fbbd 100644 --- a/Lab4/.vscode/launch.json +++ b/Lab4/.vscode/launch.json @@ -2,35 +2,13 @@ "version": "0.2.0", "configurations": [ { - "name": "ChatRoom", + "name": "ChatRoomSimpleRPC", "type": "coreclr", "request": "launch", - "preLaunchTask": "build-ChatRoom", - "program": "${workspaceFolder}/ChatRoom/bin/Debug/net6.0/ChatRoom.dll", + "preLaunchTask": "build-ChatRoomSimpleRPC", + "program": "${workspaceFolder}/ChatRoomSimpleRPC/bin/Debug/net6.0/ChatRoomSimpleRPC.dll", "args": [], - "cwd": "${workspaceFolder}/ChatRoom", - "console": "externalTerminal", - "stopAtEntry": false - }, - { - "name": "ModeratorGrpc", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-ModeratorGrpc", - "program": "${workspaceFolder}/ModeratorGrpc/bin/Debug/net6.0/ModeratorGrpc.dll", - "args": [], - "cwd": "${workspaceFolder}/ModeratorGrpc", - "console": "externalTerminal", - "stopAtEntry": false - }, - { - "name": "ParticipantGrpc", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-ParticipantGrpc", - "program": "${workspaceFolder}/ParticipantGrpc/bin/Debug/net6.0/ParticipantGrpc.dll", - "args": [], - "cwd": "${workspaceFolder}/ParticipantGrpc", + "cwd": "${workspaceFolder}/ChatRoomSimpleRPC", "console": "externalTerminal", "stopAtEntry": false }, @@ -46,57 +24,35 @@ "stopAtEntry": false }, { - "name": "ParticipantRest", + "name": "ParticipantGrpc", "type": "coreclr", "request": "launch", - "preLaunchTask": "build-ParticipantRest", - "program": "${workspaceFolder}/ParticipantRest/bin/Debug/net6.0/ParticipantRest.dll", + "preLaunchTask": "build-ParticipantGrpc", + "program": "${workspaceFolder}/ParticipantGrpc/bin/Debug/net6.0/ParticipantGrpc.dll", "args": [], - "cwd": "${workspaceFolder}/ParticipantRest", + "cwd": "${workspaceFolder}/ParticipantGrpc", "console": "externalTerminal", "stopAtEntry": false }, { - "name": "ModeratorSimpleRPC", + "name": "RestToSimpleRPCAdapter", "type": "coreclr", "request": "launch", - "preLaunchTask": "build-ModeratorSimpleRPC", - "program": "${workspaceFolder}/ModeratorSimpleRPC/bin/Debug/net6.0/ModeratorSimpleRPC.dll", + "preLaunchTask": "build-RestToSimpleRPCAdapter", + "program": "${workspaceFolder}/RestToSimpleRPCAdapter/bin/Debug/net6.0/RestToSimpleRPCAdapter.dll", "args": [], - "cwd": "${workspaceFolder}/ModeratorSimpleRPC", + "cwd": "${workspaceFolder}/RestToSimpleRPCAdapter", "console": "externalTerminal", "stopAtEntry": false }, { - "name": "ParticipantSimpleRPC", + "name": "GrpcToSimpleRPCAdapter", "type": "coreclr", "request": "launch", - "preLaunchTask": "build-ParticipantSimpleRPC", - "program": "${workspaceFolder}/ParticipantSimpleRPC/bin/Debug/net6.0/ParticipantSimpleRPC.dll", + "preLaunchTask": "build-GrpcToSimpleRPCAdapter", + "program": "${workspaceFolder}/GrpcToSimpleRPCAdapter/bin/Debug/net6.0/GrpcToSimpleRPCAdapter.dll", "args": [], - "cwd": "${workspaceFolder}/ParticipantSimpleRPC", - "console": "externalTerminal", - "stopAtEntry": false - }, - { - "name": "ModeratorRabbitMQ", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-ModeratorRabbitMQ", - "program": "${workspaceFolder}/ModeratorRabbitMQ/bin/Debug/net6.0/ModeratorRabbitMQ.dll", - "args": [], - "cwd": "${workspaceFolder}/ModeratorRabbitMQ", - "console": "externalTerminal", - "stopAtEntry": false - }, - { - "name": "ParticipantRabbitMQ", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build-ParticipantRabbitMQ", - "program": "${workspaceFolder}/ParticipantRabbitMQ/bin/Debug/net6.0/ParticipantRabbitMQ.dll", - "args": [], - "cwd": "${workspaceFolder}/ParticipantRabbitMQ", + "cwd": "${workspaceFolder}/GrpcToSimpleRPCAdapter", "console": "externalTerminal", "stopAtEntry": false } diff --git a/Lab4/.vscode/tasks.json b/Lab4/.vscode/tasks.json index 41b1f2b..a88cde1 100644 --- a/Lab4/.vscode/tasks.json +++ b/Lab4/.vscode/tasks.json @@ -2,19 +2,19 @@ "version": "2.0.0", "tasks": [ { - "label": "build-ChatRoom", + "label": "build-ChatRoomSimpleRPC", "command": "dotnet", "type": "process", "args": [ "build", - "${workspaceFolder}/ChatRoom/ChatRoom.csproj", + "${workspaceFolder}/ChatRoomSimpleRPC/ChatRoomSimpleRPC.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { - "label": "build-ModeratorGrpc", + "label": "build-ModeratorRest", "command": "dotnet", "type": "process", "args": [ @@ -25,30 +25,6 @@ ], "problemMatcher": "$msCompile" }, - { - "label": "build-ParticipantRest", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/ParticipantRest/ParticipantRest.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-ModeratorGrpc", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/ModeratorGrpc/ModeratorGrpc.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, { "label": "build-ParticipantGrpc", "command": "dotnet", @@ -62,48 +38,24 @@ "problemMatcher": "$msCompile" }, { - "label": "build-ModeratorSimpleRPC", + "label": "build-RestToSimpleRPCAdapter", "command": "dotnet", "type": "process", "args": [ "build", - "${workspaceFolder}/ModeratorSimpleRPC/ModeratorSimpleRPC.csproj", + "${workspaceFolder}/RestToSimpleRPCAdapter/RestToSimpleRPCAdapter.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { - "label": "build-ParticipantSimpleRPC", + "label": "build-GrpcToSimpleRPCAdapter", "command": "dotnet", "type": "process", "args": [ "build", - "${workspaceFolder}/ParticipantSimpleRPC/ParticipantSimpleRPC.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-ModeratorRabbitMQ", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/ModeratorRabbitMQ/ModeratorRabbitMQ.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build-ParticipantRabbitMQ", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/ParticipantRabbitMQ/ParticipantRabbitMQ.csproj", + "${workspaceFolder}/GrpcToSimpleRPCAdapter/GrpcToSimpleRPCAdapter.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], diff --git a/Lab4/ChatRoom/ChatRoomRabbitMQService.cs b/Lab4/ChatRoom/ChatRoomRabbitMQService.cs deleted file mode 100644 index 760e1e2..0000000 --- a/Lab4/ChatRoom/ChatRoomRabbitMQService.cs +++ /dev/null @@ -1,159 +0,0 @@ -using RabbitMQ.Client; -using Newtonsoft.Json; -using RabbitMQ.Client.Events; -using ChatRoomContract; -using System.Text; -using MessagePack; -using System.Diagnostics; -using NLog.LayoutRenderers.Wrappers; -using NLog; - -namespace ChatRoom; - -internal class ChatRoomRabbitMQService -{ - /// - /// Logger for this class. - /// - private Logger log = LogManager.GetCurrentClassLogger(); - - /// - /// Communications channel to RabbitMQ message broker. - /// - private IModel rmqChannel; - - /// - /// Service logic. - /// - private ChatRoomLogic logic; - - public ChatRoomRabbitMQService(ChatRoomLogic logic, IConnection connection, string exchangeName, string serverQueueName) - { - this.logic = logic; - - //get channel, configure exchanges and request queue - rmqChannel = connection.CreateModel(); - - rmqChannel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct); - rmqChannel.QueueDeclare(queue: serverQueueName, durable: true, exclusive: false, autoDelete: false, arguments: null); - rmqChannel.QueueBind(queue: serverQueueName, exchange: exchangeName, routingKey: serverQueueName, arguments: null); - - //connect to the queue as consumer - //XXX: see https://www.rabbitmq.com/dotnet-api-guide.html#concurrency for threading issues - var rmqConsumer = new EventingBasicConsumer(rmqChannel); - rmqConsumer.Received += (consumer, delivery) => OnMessageReceived(((EventingBasicConsumer)consumer).Model, delivery); - rmqChannel.BasicConsume(queue: serverQueueName, autoAck: true, consumer: rmqConsumer); - } - - /// - /// Is invoked to process messages received. - /// - /// Related communications channel. - /// Message deliver data. - private void OnMessageReceived(IModel channel, BasicDeliverEventArgs msgIn) - { - try - { - var msg = MessagePackSerializer.Deserialize(msgIn.Body); - Debug.Assert(msg != null); - - if (msg.isResponse == true) - { - return; - } - - bool hasResponse = false; - byte[]? response = null; - - switch (msg.method) - { - case nameof(IChatRoomService.RegisterClient): - { - var name = MessagePackSerializer.Deserialize(msg.args); - var clientId = logic.RegisterClient(name); - response = MessagePackSerializer.Serialize(clientId); - hasResponse = true; - break; - } - - case nameof(IChatRoomService.GetStrikes): - { - var clientId = MessagePackSerializer.Deserialize(msg.args); - var strikes = logic.GetStrikes(clientId); - response = MessagePackSerializer.Serialize(strikes); - hasResponse = true; - break; - } - - case nameof(IChatRoomService.GetBlockedUntil): - { - var clientId = MessagePackSerializer.Deserialize(msg.args); - var blockedUntil = logic.GetBlockedUntil(clientId); - response = MessagePackSerializer.Serialize(blockedUntil); - hasResponse = true; - break; - } - - case nameof(IChatRoomService.SendMessage): - { - var args = MessagePackSerializer.Deserialize(msg.args); - var success = logic.SendMessage(args.clientId, args.contents, args.needsToBeCensored); - response = MessagePackSerializer.Serialize(success); - hasResponse = true; - break; - } - - case nameof(IChatRoomService.GetNewMessage): - { - var newMessage = logic.GetNewMessage(); - response = MessagePackSerializer.Serialize(newMessage); - hasResponse = true; - break; - } - - case nameof(IChatRoomService.RejectMessage): - { - var messageId = MessagePackSerializer.Deserialize(msg.args); - logic.ApproveMessage(messageId); - break; - } - - case nameof(IChatRoomService.ApproveMessage): - { - var messageId = MessagePackSerializer.Deserialize(msg.args); - logic.ApproveMessage(messageId); - break; - } - - default: - { - throw new Exception("Unknown RPC method"); - } - } - - if (hasResponse) - { - var responseMsg = new RPCMessage - { - isResponse = true, - method = msg.method, - args = response - }; - - var properties = channel.CreateBasicProperties(); - properties.CorrelationId = msgIn.BasicProperties.CorrelationId; - - channel.BasicPublish( - exchange: msgIn.Exchange, - routingKey: msgIn.BasicProperties.ReplyTo, - basicProperties: properties, - body: MessagePackSerializer.Serialize(responseMsg) - ); - } - } - catch (Exception e) - { - log.Error(e, "Unhandled exception caught when processing a message. The message is now lost."); - } - } -} diff --git a/Lab4/ChatRoom/Server.cs b/Lab4/ChatRoom/Server.cs deleted file mode 100644 index 013f8fc..0000000 --- a/Lab4/ChatRoom/Server.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System.Net; - -using NLog; - -using SimpleRpc.Transports; -using SimpleRpc.Transports.Http.Server; -using SimpleRpc.Serialization.Hyperion; -using ChatRoomContract; -using Microsoft.Extensions.Logging; -using System.Reflection; -using System.Text.Json.Serialization; -using Microsoft.AspNetCore.Server.Kestrel.Core; - -namespace ChatRoom; - -public class Server -{ - /// - /// Logger for this class. - /// - Logger log = LogManager.GetCurrentClassLogger(); - - /// - /// Configure loggin subsystem. - /// - private void ConfigureLogging() - { - var config = new NLog.Config.LoggingConfiguration(); - - var console = - new NLog.Targets.ConsoleTarget("console") - { - Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" - }; - config.AddTarget(console); - config.AddRuleForAllLevels(console); - - LogManager.Configuration = config; - } - - /// - /// Program entry point. - /// - /// Command line arguments. - public static void Main(string[] args) - { - var self = new Server(); - self.Run(args); - } - - /// - /// Program body. - /// - /// Command line arguments. - private void Run(string[] args) - { - //configure logging - ConfigureLogging(); - - //indicate server is about to start - log.Info("Server is about to start"); - - //start the server - StartServer(args); - } - - /// - /// Starts integrated server. - /// - /// Command line arguments. - private void StartServer(string[] args) - { - Console.Title = "Chat Room"; - - var logic = new ChatRoomLogic(); - - // Simple RPC - WebApplication simpleRPCWebApplication; - { - ///create web app builder - var builder = WebApplication.CreateBuilder(args); - - //configure integrated server - builder.WebHost.ConfigureKestrel(opts => { - opts.Listen(IPAddress.Loopback, 5001); - }); - - //add SimpleRPC services - builder.Services - .AddSimpleRpcServer(new HttpServerTransportOptions { Path = "/simplerpc" }) - .AddSimpleRpcHyperionSerializer(); - - //add our custom services - builder.Services.AddSingleton(new ChatRoomSimpleRPCService(logic)); - - //build the server - var app = builder.Build(); - - //add SimpleRPC middleware - app.UseSimpleRpcServer(); - - simpleRPCWebApplication = app; - } - - // Rest, GRPC - WebApplication restGrpcWebApplication; - { - ///create web app builder - var builder = WebApplication.CreateBuilder(args); - - //configure integrated server - builder.WebHost.ConfigureKestrel(opts => { - opts.Listen(IPAddress.Loopback, 5000, opts => - { - opts.Protocols = HttpProtocols.Http2; - }); - }); - - //add and configure swagger documentation generator (http://127.0.0.1:5000/swagger/) - builder.Services.AddSwaggerGen(opts => - { - //include code comments in swagger documentation - var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - opts.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); - }); - - //turn on support for web api controllers - builder.Services - .AddControllers() - .AddJsonOptions(opts => - { - //this makes enumeration values to be strings instead of integers in opeanapi doc - opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); - }); - - //add CORS policies - builder.Services.AddCors(cr => - { - //allow everything from everywhere - cr.AddPolicy("allowAll", cp => - { - cp.AllowAnyOrigin(); - cp.AllowAnyMethod(); - cp.AllowAnyHeader(); - }); - }); - - //publish the background logic as (an internal) service through dependency injection, - //otherwise it will not start until the first client calls into controller - builder.Services.AddSingleton(logic); - - //add support for GRPC services - builder.Services.AddGrpc(); - - builder.Services.AddSingleton(new ChatRoomGrpcService(logic)); - - //build the server - var app = builder.Build(); - - //turn CORS policy on - app.UseCors("allowAll"); - - //turn on support for swagger doc web page - app.UseSwagger(); - app.UseSwaggerUI(); - - app.MapGrpcService(); - - ////turn on request routing - app.UseRouting(); - - ////configure routes - app.MapControllerRoute( - name: "default", - pattern: "{controller}/{action=Index}/{id?}" - ); - - restGrpcWebApplication = app; - } - - // RabbitMQ - { - var service = new ChatRoomRabbitMQService( - logic, - RabbitMQConfig.CreateConnection(), - RabbitMQConfig.ExchangeName, - RabbitMQConfig.ServerQueueName - ); - } - - var restGrpcTask = restGrpcWebApplication.RunAsync(); - var simpleRPCTask = simpleRPCWebApplication.RunAsync(); - - restGrpcTask.Wait(); - simpleRPCTask.Wait(); - } -} diff --git a/Lab4/ChatRoomContract/ChatRoomContract.csproj b/Lab4/ChatRoomContract/ChatRoomContract.csproj index 7fe6a53..aa9acec 100644 --- a/Lab4/ChatRoomContract/ChatRoomContract.csproj +++ b/Lab4/ChatRoomContract/ChatRoomContract.csproj @@ -11,32 +11,17 @@ - - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/Lab4/ChatRoomContract/ChatRoomGrpcClient.cs b/Lab4/ChatRoomContract/ChatRoomGrpcClient.cs deleted file mode 100644 index a583e96..0000000 --- a/Lab4/ChatRoomContract/ChatRoomGrpcClient.cs +++ /dev/null @@ -1,116 +0,0 @@ - -using ChatRoomContract.Protocol; -using Google.Protobuf.WellKnownTypes; -using Grpc.Net.Client; - -namespace ChatRoomContract; - -public class ChatRoomGrpcClient : IChatRoomService -{ - GrpcChannel channel; - ChatRoom.ChatRoomClient client; - - public ChatRoomGrpcClient(string address) - { - channel = GrpcChannel.ForAddress(address); - client = new ChatRoom.ChatRoomClient(channel); - } - - /// - /// Approve a message - /// - /// Message ID - public void ApproveMessage(int messageId) - { - client.ApproveMessage(new MessageId { Id = messageId }); - } - - /// - /// Get timestamp until when the client is blocked - /// - /// Client ID - /// Optional datetime object - public DateTime? GetBlockedUntil(int clientId) - { - var result = client.GetBlockedUntil(new ClientId { Id = clientId }); - if (result.HasTimestamp) - { - return result.Timestamp.ToDateTime(); - } - else - { - return null; - } - } - - /// - /// Get the next message which hasn't been approved or rejected - /// - /// Message object. Returns null if there is no message - public Message? GetNewMessage() - { - var result = client.GetNewMessage(new Empty()); - if (result.HasMessage) - { - return new Message - { - id = result.Message.Id, - contents = result.Message.Contents, - needsToBeCensored = result.Message.NeedsToBeCensored - }; - } - else - { - return null; - } - } - - /// - /// Get number of strikes a participant has - /// - /// Client ID - /// Number of strikes - public int GetStrikes(int clientId) - { - var result = client.GetStrikes(new ClientId { Id = clientId }); - return result.Strikes; - } - - /// - /// Register client with a name - /// - /// Name of client, can be duplicate between clients - /// Client ID - public int RegisterClient(string name) - { - var result = client.RegisterClient(new RegisterClientRequest { Name = name }); - return result.Id; - } - - /// - /// Reject a message - /// - /// Message ID - public void RejectMessage(int messageId) - { - client.RejectMessage(new MessageId { Id = messageId }); - } - - /// - /// Send a message, will be given to a moderator to be approved - /// - /// Client ID - /// Message contents - /// Does this message need to be censored? - /// Was sending successful, can fail if user is blocked - public bool SendMessage(int clientId, string contents, bool needsToBeCensored) - { - var result = client.SendMessage(new UserMessageRequest - { - ClientId = clientId, - Contents = contents, - NeedsToBeCensored = needsToBeCensored - }); - return result.Success; - } -} \ No newline at end of file diff --git a/Lab4/ChatRoomContract/ChatRoomRabbitMQClient.cs b/Lab4/ChatRoomContract/ChatRoomRabbitMQClient.cs deleted file mode 100644 index 66427c8..0000000 --- a/Lab4/ChatRoomContract/ChatRoomRabbitMQClient.cs +++ /dev/null @@ -1,243 +0,0 @@ -using MessagePack; -using RabbitMQ.Client; -using RabbitMQ.Client.Events; - -namespace ChatRoomContract; - -/// -/// RabbitMQ chat room client -/// -public class ChatRoomRabbitMQClient : IChatRoomService -{ - /// - /// Exchange name - /// - private string exchangeName; - /// - /// Client queue name - /// - private string clientQueueName; - /// - /// Server queue name - /// - private string serverQueueName; - /// - /// RabbitMQ channel - /// - private IModel rmqChannel; - - /// - /// Chat Room client constructor - /// - /// RabbitMQ connection - /// Exchange name - /// Client queue name - /// Server queue name - public ChatRoomRabbitMQClient(IConnection connection, string exchangeName, string clientQueueName, string serverQueueName) - { - this.exchangeName = exchangeName; - this.clientQueueName = clientQueueName; - this.serverQueueName = serverQueueName; - rmqChannel = connection.CreateModel(); - - rmqChannel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct); - rmqChannel.QueueDeclare(queue: clientQueueName, durable: false, exclusive: true, autoDelete: false, arguments: null); - rmqChannel.QueueBind(queue: clientQueueName, exchange: exchangeName, routingKey: clientQueueName, arguments: null); - } - - /// - /// Send rpc message without waiting for a response - /// - /// Method name - /// Serialized arguments - /// Optional correlation ID - private void CallVoid(string method, byte[] args, string? correlationId = null) - { - correlationId ??= Guid.NewGuid().ToString(); - - var requestProps = rmqChannel.CreateBasicProperties(); - requestProps.CorrelationId = correlationId; - requestProps.ReplyTo = clientQueueName; - - var msg = new RPCMessage - { - isResponse = false, - method = method, - args = args - }; - - rmqChannel.BasicPublish( - exchange: exchangeName, - routingKey: serverQueueName, - basicProperties: requestProps, - body: MessagePackSerializer.Serialize(msg) - ); - } - - /// - /// Send a rpc message and wait for a response - /// - /// Result type - /// Method name - /// Serialized arguments - /// Result - private ResultType Call(string method, byte[]? args) - { - var correlationId = Guid.NewGuid().ToString(); - var isResultReady = false; - var resultReadySignal = new AutoResetEvent(false); - - ResultType result = default; - - //ensure contents of variables set in main thread, are loadable by receiver thread - Thread.MemoryBarrier(); - - //create response message consumer - var consumer = new EventingBasicConsumer(rmqChannel); - consumer.Received += - (channel, delivery) => { - //ensure contents of variables set in main thread are loaded into this thread - Thread.MemoryBarrier(); - - if (isResultReady) - { - return; - } - - if (delivery.BasicProperties.CorrelationId != correlationId) - { - return; - } - - - var msg = MessagePackSerializer.Deserialize(delivery.Body); - if (msg.isResponse && msg.method == method) - { - if (msg.args != null) - { - result = MessagePackSerializer.Deserialize(msg.args); - } - - //indicate result has been received, ensure it is loadable by main thread - isResultReady = true; - Thread.MemoryBarrier(); - - //signal main thread that result has been received - resultReadySignal.Set(); - } - }; - - //attach message consumer to the response queue - var consumerTag = rmqChannel.BasicConsume(clientQueueName, true, consumer); - - CallVoid(method, args, correlationId); - - //wait for the result to be ready - resultReadySignal.WaitOne(); - - //ensure contents of variables set by the receiver are loaded into this thread - Thread.MemoryBarrier(); - - //detach message consumer from the response queue - rmqChannel.BasicCancel(consumerTag); - - return result; - } - - /// - /// Approve a message - /// - /// Message ID - public void ApproveMessage(int messageId) - { - CallVoid( - nameof(IChatRoomService.ApproveMessage), - MessagePackSerializer.Serialize(messageId) - ); - } - - /// - /// Get timestamp until when the client is blocked - /// - /// Client ID - /// Optional datetime object - public DateTime? GetBlockedUntil(int clientId) - { - return Call( - nameof(IChatRoomService.GetBlockedUntil), - MessagePackSerializer.Serialize(clientId) - ); - } - - /// - /// Get the next message which hasn't been approved or rejected - /// - /// Message object. Returns null if there is no message - public Message? GetNewMessage() - { - return Call( - nameof(IChatRoomService.GetNewMessage), - null - ); - } - - /// - /// Get number of strikes a participant has - /// - /// Client ID - /// Number of strikes - public int GetStrikes(int clientId) - { - return Call( - nameof(IChatRoomService.GetStrikes), - MessagePackSerializer.Serialize(clientId) - ); - } - - /// - /// Register client with a name - /// - /// Name of client, can be duplicate between clients - /// Client ID - public int RegisterClient(string name) - { - return Call( - nameof(IChatRoomService.RegisterClient), - MessagePackSerializer.Serialize(name) - ); - } - - /// - /// Reject a message - /// - /// Message ID - public void RejectMessage(int messageId) - { - CallVoid( - nameof(IChatRoomService.RejectMessage), - MessagePackSerializer.Serialize(messageId) - ); - } - - /// - /// Send a message, will be given to a moderator to be approved - /// - /// Client ID - /// Message contents - /// Does this message need to be censored? - /// Was sending successful, can fail if user is blocked - public bool SendMessage(int clientId, string contents, bool needsToBeCensored) - { - var args = new SendMessageArgs - { - clientId = clientId, - contents = contents, - needsToBeCensored = needsToBeCensored - }; - - return Call( - nameof(IChatRoomService.SendMessage), - MessagePackSerializer.Serialize(args) - ); - } -} diff --git a/Lab4/ChatRoomContract/ChatRoomRestClient.cs b/Lab4/ChatRoomContract/ChatRoomRestClient.cs deleted file mode 100644 index dbc2c59..0000000 --- a/Lab4/ChatRoomContract/ChatRoomRestClient.cs +++ /dev/null @@ -1,124 +0,0 @@ - -using NswagGenerated; - -namespace ChatRoomContract; - -/// -/// Wrapper around generated NSwag client -/// -public class ChatRoomRestClient : IChatRoomService -{ - NswagGenerated.NswagChatRoomClient nswag; - - /// - /// Chat room client constructor - /// - /// Server base url - /// HTTP Client - public ChatRoomRestClient(string baseUrl, HttpClient httpClient) - { - nswag = new NswagGenerated.NswagChatRoomClient(baseUrl, httpClient); - } - - /// - /// Approve a message - /// - /// Message ID - public void ApproveMessage(int messageId) - { - nswag.ApproveMessage(messageId); - } - - /// - /// Get timestamp until when the client is blocked - /// - /// Client ID - /// Optional datetime object - public DateTime? GetBlockedUntil(int clientId) - { - try - { - var offset = nswag.GetBlockedUntil(clientId); - return offset.DateTime; - } - catch (ApiException e) - { - if (e.StatusCode == 204) - { - return null; - } - - throw; - } - } - - /// - /// Get the next message which hasn't been approved or rejected - /// - /// Message object. Returns null if there is no message - public Message? GetNewMessage() - { - NswagGenerated.Message message; - try - { - message = nswag.GetNewMessage(); - } - catch (ApiException e) - { - if (e.StatusCode == 204) - { - return null; - } - - throw; - } - - return new Message - { - id = message.Id, - contents = message.Contents, - needsToBeCensored = message.NeedsToBeCensored - }; - } - - /// - /// Get number of strikes a participant has - /// - /// Client ID - /// Number of strikes - public int GetStrikes(int clientId) - { - return nswag.GetStrikes(clientId); - } - - /// - /// Register client with a name - /// - /// Name of client, can be duplicate between clients - /// Client ID - public int RegisterClient(string name) - { - return nswag.RegisterClient(name); - } - - /// - /// Reject a message - /// - /// Message ID - public void RejectMessage(int messageId) - { - nswag.RejectMessage(messageId); - } - - /// - /// Send a message, will be given to a moderator to be approved - /// - /// Client ID - /// Message contents - /// Does this message need to be censored? - /// Was sending successful, can fail if user is blocked - public bool SendMessage(int clientId, string contents, bool needsToBeCensored) - { - return nswag.SendMessage(clientId, contents, needsToBeCensored); - } -} \ No newline at end of file diff --git a/Lab2-grpc/ChatRoomContract/ChatRoomClient.cs b/Lab4/ChatRoomContract/GrpcChatRoomClient.cs similarity index 97% rename from Lab2-grpc/ChatRoomContract/ChatRoomClient.cs rename to Lab4/ChatRoomContract/GrpcChatRoomClient.cs index 975684d..7e37fcf 100644 --- a/Lab2-grpc/ChatRoomContract/ChatRoomClient.cs +++ b/Lab4/ChatRoomContract/GrpcChatRoomClient.cs @@ -5,12 +5,12 @@ using Grpc.Net.Client; namespace ChatRoomContract; -public class ChatRoomClient : IChatRoomService +public class GrpcChatRoomClient : IChatRoomService { GrpcChannel channel; ChatRoom.ChatRoomClient client; - public ChatRoomClient(string address) + public GrpcChatRoomClient(string address) { channel = GrpcChannel.ForAddress(address); client = new ChatRoom.ChatRoomClient(channel); diff --git a/Lab4/ChatRoomContract/IChatRoomContract.cs b/Lab4/ChatRoomContract/IChatRoomService.cs similarity index 95% rename from Lab4/ChatRoomContract/IChatRoomContract.cs rename to Lab4/ChatRoomContract/IChatRoomService.cs index a5d9b11..1e57a5b 100644 --- a/Lab4/ChatRoomContract/IChatRoomContract.cs +++ b/Lab4/ChatRoomContract/IChatRoomService.cs @@ -1,26 +1,21 @@ -using MessagePack; -namespace ChatRoomContract; +namespace ChatRoomContract; /// /// Minimal message description /// -[MessagePackObject] public class Message { /// /// Message ID /// - [Key(0)] public int id; /// /// Message contents /// - [Key(1)] public string contents; /// /// Does this message need to be censored? /// - [Key(2)] public bool needsToBeCensored; } diff --git a/Lab4/ChatRoomContract/NswagChatRoomClient.cs b/Lab4/ChatRoomContract/NswagChatRoomClient.cs index 9256f31..5bebd74 100644 --- a/Lab4/ChatRoomContract/NswagChatRoomClient.cs +++ b/Lab4/ChatRoomContract/NswagChatRoomClient.cs @@ -1,4 +1,4 @@ -//---------------------- +//---------------------- // // Generated using the NSwag toolchain v14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) // @@ -23,19 +23,19 @@ namespace NswagGenerated using System = global::System; [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class NswagChatRoomClient + public partial class NswagChatRoomClient { -#pragma warning disable 8618 + #pragma warning disable 8618 private string _baseUrl; -#pragma warning restore 8618 + #pragma warning restore 8618 private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public NswagChatRoomClient(string baseUrl, System.Net.Http.HttpClient httpClient) -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { BaseUrl = baseUrl; _httpClient = httpClient; @@ -860,7 +860,7 @@ namespace NswagGenerated var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); if (field != null) { - var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) as System.Runtime.Serialization.EnumMemberAttribute; if (attribute != null) { @@ -872,13 +872,13 @@ namespace NswagGenerated return converted == null ? string.Empty : converted; } } - else if (value is bool) + else if (value is bool) { return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); } else if (value is byte[]) { - return System.Convert.ToBase64String((byte[])value); + return System.Convert.ToBase64String((byte[]) value); } else if (value is string[]) { @@ -953,10 +953,10 @@ namespace NswagGenerated } -#pragma warning restore 108 -#pragma warning restore 114 -#pragma warning restore 472 -#pragma warning restore 612 +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 #pragma warning restore 1573 #pragma warning restore 1591 #pragma warning restore 8073 diff --git a/Lab4/ChatRoomContract/RPCMessage.cs b/Lab4/ChatRoomContract/RPCMessage.cs deleted file mode 100644 index 2acc5b1..0000000 --- a/Lab4/ChatRoomContract/RPCMessage.cs +++ /dev/null @@ -1,49 +0,0 @@ -using MessagePack; - -namespace ChatRoomContract; - -/// -/// RabbitMQ message -/// -[MessagePackObject] -public class RPCMessage -{ - /// - /// Is this message a response - /// - [Key(0)] - public bool isResponse; - /// - /// Method name - /// - [Key(1)] - public string method; - /// - /// Optional arguments - /// - [Key(2)] - public byte[]? args; -} - -/// -/// IChatRoomService.SendMessage arguments -/// -[MessagePackObject] -public class SendMessageArgs -{ - /// - /// Client ID - /// - [Key(0)] - public int clientId { get; set; } - /// - /// Message contents - /// - [Key(1)] - public string contents { get; set; } - /// - /// Does this message need to be censored? - /// - [Key(2)] - public bool needsToBeCensored { get; set; } -} \ No newline at end of file diff --git a/Lab4/ChatRoomContract/RabbitMQConfig.cs b/Lab4/ChatRoomContract/RabbitMQConfig.cs deleted file mode 100644 index 8a1fe2a..0000000 --- a/Lab4/ChatRoomContract/RabbitMQConfig.cs +++ /dev/null @@ -1,30 +0,0 @@ -using RabbitMQ.Client; - -namespace ChatRoomContract; - -public static class RabbitMQConfig -{ - public static string ExchangeName = "T120B180.ChatRoom.Exchange"; - public static string ServerQueueName = "T120B180.ChatRoom.Server"; - public static string ClientQueueNamePrefix = "T120B180.ChatRoom.Client_"; - public static string HostName = "localhost"; - public static string Username = "guest"; - public static string Password = "guest"; - - public static string CreateClientQueueName() - { - var ClientId = Guid.NewGuid().ToString(); - return ClientQueueNamePrefix + ClientId; - } - - public static IConnection CreateConnection() - { - var rmqConnectionFactory = new ConnectionFactory - { - HostName = HostName, - UserName = Username, - Password = Password - }; - return rmqConnectionFactory.CreateConnection(); - } -} diff --git a/Lab2-rest/ChatRoomContract/ChatRoomClient.cs b/Lab4/ChatRoomContract/RestChatRoomClient.cs similarity index 96% rename from Lab2-rest/ChatRoomContract/ChatRoomClient.cs rename to Lab4/ChatRoomContract/RestChatRoomClient.cs index 3f3d3b4..6b0575f 100644 --- a/Lab2-rest/ChatRoomContract/ChatRoomClient.cs +++ b/Lab4/ChatRoomContract/RestChatRoomClient.cs @@ -6,7 +6,7 @@ namespace ChatRoomContract; /// /// Wrapper around generated NSwag client /// -public class ChatRoomClient : IChatRoomService +public class RestChatRoomClient : IChatRoomService { NswagGenerated.NswagChatRoomClient nswag; @@ -15,7 +15,7 @@ public class ChatRoomClient : IChatRoomService /// /// Server base url /// HTTP Client - public ChatRoomClient(string baseUrl, HttpClient httpClient) + public RestChatRoomClient(string baseUrl, HttpClient httpClient) { nswag = new NswagGenerated.NswagChatRoomClient(baseUrl, httpClient); } diff --git a/Lab4/ChatRoomContract/nswag.json b/Lab4/ChatRoomContract/nswag.json index 921b2a1..1f4e5a1 100644 --- a/Lab4/ChatRoomContract/nswag.json +++ b/Lab4/ChatRoomContract/nswag.json @@ -1,4 +1,4 @@ -{ +{ "runtime": "Net60", "documentGenerator": { "fromDocument": { diff --git a/Lab4/ChatRoom/ChatRoomLogic.cs b/Lab4/ChatRoomSimpleRPC/ChatRoomLogic.cs similarity index 99% rename from Lab4/ChatRoom/ChatRoomLogic.cs rename to Lab4/ChatRoomSimpleRPC/ChatRoomLogic.cs index 7d58b0f..6e5c606 100644 --- a/Lab4/ChatRoom/ChatRoomLogic.cs +++ b/Lab4/ChatRoomSimpleRPC/ChatRoomLogic.cs @@ -1,4 +1,5 @@ -using NLog; +using Microsoft.Extensions.Logging; +using NLog; namespace ChatRoom; diff --git a/Lab4/ChatRoom/ChatRoomSimpleRPCService.cs b/Lab4/ChatRoomSimpleRPC/ChatRoomService.cs similarity index 75% rename from Lab4/ChatRoom/ChatRoomSimpleRPCService.cs rename to Lab4/ChatRoomSimpleRPC/ChatRoomService.cs index 98b0ea1..938c303 100644 --- a/Lab4/ChatRoom/ChatRoomSimpleRPCService.cs +++ b/Lab4/ChatRoomSimpleRPC/ChatRoomService.cs @@ -1,13 +1,10 @@ -namespace ChatRoom; + +namespace ChatRoom; -public class ChatRoomSimpleRPCService : ChatRoomContract.IChatRoomService +public class ChatRoomService : ChatRoomContract.IChatRoomService { - private readonly ChatRoomLogic logic; - - public ChatRoomSimpleRPCService(ChatRoomLogic logic) - { - this.logic = logic; - } + //NOTE: instance-per-request service would need logic to be static or injected from a singleton instance + private readonly ChatRoomLogic logic = new ChatRoomLogic(); public int RegisterClient(string name) { diff --git a/Lab4/ModeratorSimpleRPC/ModeratorSimpleRPC.csproj b/Lab4/ChatRoomSimpleRPC/ChatRoomSimpleRPC.csproj similarity index 70% rename from Lab4/ModeratorSimpleRPC/ModeratorSimpleRPC.csproj rename to Lab4/ChatRoomSimpleRPC/ChatRoomSimpleRPC.csproj index 5ad18e7..7fb155d 100644 --- a/Lab4/ModeratorSimpleRPC/ModeratorSimpleRPC.csproj +++ b/Lab4/ChatRoomSimpleRPC/ChatRoomSimpleRPC.csproj @@ -1,14 +1,12 @@ - + - Exe net6.0 - enable enable + enable - @@ -16,7 +14,6 @@ - diff --git a/Lab4/ChatRoom/ChatRoomState.cs b/Lab4/ChatRoomSimpleRPC/ChatRoomState.cs similarity index 100% rename from Lab4/ChatRoom/ChatRoomState.cs rename to Lab4/ChatRoomSimpleRPC/ChatRoomState.cs diff --git a/Lab4/ChatRoom/Properties/launchSettings.json b/Lab4/ChatRoomSimpleRPC/Properties/launchSettings.json similarity index 100% rename from Lab4/ChatRoom/Properties/launchSettings.json rename to Lab4/ChatRoomSimpleRPC/Properties/launchSettings.json diff --git a/Lab4/ChatRoomSimpleRPC/Server.cs b/Lab4/ChatRoomSimpleRPC/Server.cs new file mode 100644 index 0000000..7c18d81 --- /dev/null +++ b/Lab4/ChatRoomSimpleRPC/Server.cs @@ -0,0 +1,100 @@ +using System.Net; + +using NLog; + +using SimpleRpc.Transports; +using SimpleRpc.Transports.Http.Server; +using SimpleRpc.Serialization.Hyperion; +using ChatRoomContract; +using Microsoft.Extensions.Logging; + +namespace ChatRoom; + +public class Server +{ + /// + /// Logger for this class. + /// + Logger log = LogManager.GetCurrentClassLogger(); + + /// + /// Configure loggin subsystem. + /// + private void ConfigureLogging() + { + var config = new NLog.Config.LoggingConfiguration(); + + var console = + new NLog.Targets.ConsoleTarget("console") + { + Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" + }; + config.AddTarget(console); + config.AddRuleForAllLevels(console); + + LogManager.Configuration = config; + } + + /// + /// Program entry point. + /// + /// Command line arguments. + public static void Main(string[] args) + { + var self = new Server(); + self.Run(args); + } + + /// + /// Program body. + /// + /// Command line arguments. + private void Run(string[] args) + { + //configure logging + ConfigureLogging(); + + //indicate server is about to start + log.Info("Server is about to start"); + + //start the server + StartServer(args); + } + + /// + /// Starts integrated server. + /// + /// Command line arguments. + private void StartServer(string[] args) + { + Console.Title = "Chat Room"; + + ///create web app builder + var builder = WebApplication.CreateBuilder(args); + + //configure integrated server + builder.WebHost.ConfigureKestrel(opts => { + opts.Listen(IPAddress.Loopback, 5000); + }); + + //add SimpleRPC services + builder.Services + .AddSimpleRpcServer(new HttpServerTransportOptions { Path = "/simplerpc" }) + .AddSimpleRpcHyperionSerializer(); + + //add our custom services + builder.Services + // .AddScoped(); //instance-per-request, AddTransient would result in the same + .AddSingleton(new ChatRoomService()); //singleton + + //build the server + var app = builder.Build(); + + //add SimpleRPC middleware + app.UseSimpleRpcServer(); + + //run the server + app.Run(); + // app.RunAsync(); //use this if you need to implement background processing in the main thread + } +} diff --git a/Lab4/ChatRoom/appsettings.json b/Lab4/ChatRoomSimpleRPC/appsettings.json similarity index 100% rename from Lab4/ChatRoom/appsettings.json rename to Lab4/ChatRoomSimpleRPC/appsettings.json diff --git a/Lab4/ChatRoom/ChatRoomGrpcService.cs b/Lab4/GrpcToSimpleRPCAdapter/ChatRoomService.cs similarity index 80% rename from Lab4/ChatRoom/ChatRoomGrpcService.cs rename to Lab4/GrpcToSimpleRPCAdapter/ChatRoomService.cs index 8055b3a..cce8425 100644 --- a/Lab4/ChatRoom/ChatRoomGrpcService.cs +++ b/Lab4/GrpcToSimpleRPCAdapter/ChatRoomService.cs @@ -1,15 +1,18 @@ using Google.Protobuf.WellKnownTypes; using Grpc.Core; using ChatRoomContract.Protocol; +using ChatRoomContract; -namespace ChatRoom; +namespace GrpcToSimpleRPCAdapter; -public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBase +public class ChatRoomService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBase { - private readonly ChatRoomLogic logic; - public ChatRoomGrpcService(ChatRoomLogic logic) + //NOTE: instance-per-request service would need logic to be static or injected from a singleton instance + private readonly IChatRoomService service; + + public ChatRoomService(IChatRoomService service) { - this.logic = logic; + this.service = service; } /// @@ -20,7 +23,7 @@ public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBa /// Client ID public override Task RegisterClient(RegisterClientRequest request, ServerCallContext context) { - var result = new ClientId { Id = logic.RegisterClient(request.Name) }; + var result = new ClientId { Id = service.RegisterClient(request.Name) }; return Task.FromResult(result); } @@ -32,7 +35,7 @@ public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBa /// Number of strikes public override Task GetStrikes(ClientId request, ServerCallContext context) { - var result = new Srikes { Strikes = logic.GetStrikes(request.Id) }; + var result = new Srikes { Strikes = service.GetStrikes(request.Id) }; return Task.FromResult(result); } @@ -44,7 +47,7 @@ public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBa /// Optional datetime object public override Task GetBlockedUntil(ClientId request, ServerCallContext context) { - var timestamp = logic.GetBlockedUntil(request.Id); + var timestamp = service.GetBlockedUntil(request.Id); var result = new BlockedUntil { HasTimestamp = false }; if (timestamp != null) { @@ -62,7 +65,7 @@ public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBa /// Was sending successful, can fail if user is blocked public override Task SendMessage(UserMessageRequest request, ServerCallContext context) { - var success = logic.SendMessage(request.ClientId, request.Contents, request.NeedsToBeCensored); + var success = service.SendMessage(request.ClientId, request.Contents, request.NeedsToBeCensored); var result = new BoolResponse { Success = success }; return Task.FromResult(result); } @@ -75,7 +78,7 @@ public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBa /// Message object. Returns null if there is no message public override Task GetNewMessage(Empty request, ServerCallContext context) { - var message = logic.GetNewMessage(); + var message = service.GetNewMessage(); var result = new NewUserMessage { HasMessage = false, Message = new UserMessage() }; if (message != null) { @@ -95,7 +98,7 @@ public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBa /// Empty public override Task ApproveMessage(MessageId request, ServerCallContext context) { - logic.ApproveMessage(request.Id); + service.ApproveMessage(request.Id); return Task.FromResult(new Empty()); } @@ -107,7 +110,7 @@ public class ChatRoomGrpcService : ChatRoomContract.Protocol.ChatRoom.ChatRoomBa /// Empty public override Task RejectMessage(MessageId request, ServerCallContext context) { - logic.RejectMessage(request.Id); + service.RejectMessage(request.Id); return Task.FromResult(new Empty()); } } diff --git a/Lab4/ParticipantSimpleRPC/ParticipantSimpleRPC.csproj b/Lab4/GrpcToSimpleRPCAdapter/GrpcToSimpleRPCAdapter.csproj similarity index 69% rename from Lab4/ParticipantSimpleRPC/ParticipantSimpleRPC.csproj rename to Lab4/GrpcToSimpleRPCAdapter/GrpcToSimpleRPCAdapter.csproj index 903a2e0..7fb155d 100644 --- a/Lab4/ParticipantSimpleRPC/ParticipantSimpleRPC.csproj +++ b/Lab4/GrpcToSimpleRPCAdapter/GrpcToSimpleRPCAdapter.csproj @@ -1,14 +1,12 @@ - + - Exe net6.0 - enable enable + enable - @@ -16,7 +14,6 @@ - diff --git a/Lab4/GrpcToSimpleRPCAdapter/Properties/launchSettings.json b/Lab4/GrpcToSimpleRPCAdapter/Properties/launchSettings.json new file mode 100644 index 0000000..9974745 --- /dev/null +++ b/Lab4/GrpcToSimpleRPCAdapter/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "ChatRoom": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:56849;http://localhost:56850" + } + } +} \ No newline at end of file diff --git a/Lab4/GrpcToSimpleRPCAdapter/Server.cs b/Lab4/GrpcToSimpleRPCAdapter/Server.cs new file mode 100644 index 0000000..e30095f --- /dev/null +++ b/Lab4/GrpcToSimpleRPCAdapter/Server.cs @@ -0,0 +1,122 @@ + +using ChatRoomContract; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Logging; +using SimpleRpc.Serialization.Hyperion; +using SimpleRpc.Transports; +using SimpleRpc.Transports.Http.Client; +using System.Diagnostics; +using System.Net; +using NLog; + +namespace GrpcToSimpleRPCAdapter; + +public class Server +{ + public static void Main(string[] args) + { + var self = new Server(); + self.Run(args); + } + + /// + /// Logger for this class. + /// + Logger log = LogManager.GetCurrentClassLogger(); + + /// + /// Configures logging subsystem. + /// + private void ConfigureLogging() + { + var config = new NLog.Config.LoggingConfiguration(); + + var console = + new NLog.Targets.ConsoleTarget("console") + { + Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" + }; + config.AddTarget(console); + config.AddRuleForAllLevels(console); + + LogManager.Configuration = config; + } + + /// + /// Program body. + /// + /// Command line arguments. + private void Run(string[] args) + { + //configure logging + ConfigureLogging(); + + //indicate server is about to start + log.Info("Server is about to start"); + + //start the server + StartServer(args); + } + + public IChatRoomService getSimpleRPCService() + { + //connect to the server, get service client proxy + var sc = new ServiceCollection(); + sc + .AddSimpleRpcClient( + "chatRoomService", //must be same as on line 86 + new HttpClientTransportOptions + { + Url = "http://127.0.0.1:5000/simplerpc", + Serializer = "HyperionMessageSerializer" + } + ) + .AddSimpleRpcHyperionSerializer(); + + sc.AddSimpleRpcProxy("chatRoomService"); //must be same as on line 77 + + var sp = sc.BuildServiceProvider(); + + var chatRoom = sp.GetService(); + Debug.Assert(chatRoom != null); + + return chatRoom; + } + + /// + /// Starts integrated server. + /// + /// Command line arguments. + private void StartServer(string[] args) + { + //create web app builder + var builder = WebApplication.CreateBuilder(args); + + //configure integrated server + builder.WebHost.ConfigureKestrel(opts => { + opts.Listen(IPAddress.Loopback, 5002, opts => + { + opts.Protocols = HttpProtocols.Http2; + }); + }); + + //add support for GRPC services + builder.Services.AddGrpc(); + + //add the actual services + builder.Services.AddSingleton(getSimpleRPCService()); + + //build the server + var app = builder.Build(); + + //turn on request routing + app.UseRouting(); + + //configure routes + app.MapGrpcService(); + + //run the server + app.Run(); + // app.RunAsync(); //use this if you need to implement background processing in the main thread + } +} \ No newline at end of file diff --git a/Lab4/GrpcToSimpleRPCAdapter/appsettings.json b/Lab4/GrpcToSimpleRPCAdapter/appsettings.json new file mode 100644 index 0000000..ae459eb --- /dev/null +++ b/Lab4/GrpcToSimpleRPCAdapter/appsettings.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "Microsoft.AspNetCore.Hosting.Diagnostics": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Lab4/Lab4.sln b/Lab4/Lab4.sln index 36242a4..6f58121 100644 --- a/Lab4/Lab4.sln +++ b/Lab4/Lab4.sln @@ -3,29 +3,17 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.11.35208.52 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatRoom", "ChatRoom\ChatRoom.csproj", "{0F2C1DA4-5EC0-4287-A27D-5DA3C2FF7F62}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestToSimpleRPCAdapter", "RestToSimpleRPCAdapter\RestToSimpleRPCAdapter.csproj", "{342A1012-23DF-4D2C-9E37-D8B6175C0D55}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatRoomContract", "ChatRoomContract\ChatRoomContract.csproj", "{301234B6-13D6-4947-BCEC-1287E7CFCA6F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatRoomContract", "ChatRoomContract\ChatRoomContract.csproj", "{82F1B5A7-7D2E-40B8-9DFE-0B752A00272F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModeratorSimpleRPC", "ModeratorSimpleRPC\ModeratorSimpleRPC.csproj", "{1258DF7D-83C6-49AF-8A47-4A06F816846F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatRoomSimpleRPC", "ChatRoomSimpleRPC\ChatRoomSimpleRPC.csproj", "{4F2C26C6-F0A2-4427-82E9-9619831EEBE0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParticipantSimpleRPC", "ParticipantSimpleRPC\ParticipantSimpleRPC.csproj", "{1228253D-45D1-477F-93F3-99C2741CF827}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModeratorRest", "ModeratorRest\ModeratorRest.csproj", "{ED518130-CADD-4D9F-8E42-48DBB43DD131}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModeratorRest", "ModeratorRest\ModeratorRest.csproj", "{64B1DFC1-B9AC-46D5-951E-7B66EFC47DA6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcToSimpleRPCAdapter", "GrpcToSimpleRPCAdapter\GrpcToSimpleRPCAdapter.csproj", "{793C59B0-7712-49A5-8A49-C1527FCA4080}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParticipantRest", "ParticipantRest\ParticipantRest.csproj", "{8C97E0F7-5438-4B30-B3F7-DB1757E784C8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moderator", "Moderator\Moderator.csproj", "{6DFD9D6C-B52B-44C4-8246-6ACC970A55F8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Participant", "Participant\Participant.csproj", "{B307B77D-47D1-4603-AF04-35F9D5F2BDE0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModeratorGrpc", "ModeratorGrpc\ModeratorGrpc.csproj", "{906F9E24-D852-44DD-8CB6-9A7EF70A09D7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParticipantGrpc", "ParticipantGrpc\ParticipantGrpc.csproj", "{C14A7CA4-96DA-498A-B8A9-291AE54A5BD5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModeratorRabbitMQ", "ModeratorRabbitMQ\ModeratorRabbitMQ.csproj", "{065DF942-2AFF-44A0-AA7A-44CCC5446848}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParticipantRabbitMQ", "ParticipantRabbitMQ\ParticipantRabbitMQ.csproj", "{9434774F-B80A-490F-A57A-52031CC2F5C6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParticipantGrpc", "ParticipantGrpc\ParticipantGrpc.csproj", "{798A8C74-E96E-455D-81DB-AFFBA53140FB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -33,59 +21,35 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0F2C1DA4-5EC0-4287-A27D-5DA3C2FF7F62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0F2C1DA4-5EC0-4287-A27D-5DA3C2FF7F62}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0F2C1DA4-5EC0-4287-A27D-5DA3C2FF7F62}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0F2C1DA4-5EC0-4287-A27D-5DA3C2FF7F62}.Release|Any CPU.Build.0 = Release|Any CPU - {301234B6-13D6-4947-BCEC-1287E7CFCA6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {301234B6-13D6-4947-BCEC-1287E7CFCA6F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {301234B6-13D6-4947-BCEC-1287E7CFCA6F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {301234B6-13D6-4947-BCEC-1287E7CFCA6F}.Release|Any CPU.Build.0 = Release|Any CPU - {1258DF7D-83C6-49AF-8A47-4A06F816846F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1258DF7D-83C6-49AF-8A47-4A06F816846F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1258DF7D-83C6-49AF-8A47-4A06F816846F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1258DF7D-83C6-49AF-8A47-4A06F816846F}.Release|Any CPU.Build.0 = Release|Any CPU - {1228253D-45D1-477F-93F3-99C2741CF827}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1228253D-45D1-477F-93F3-99C2741CF827}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1228253D-45D1-477F-93F3-99C2741CF827}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1228253D-45D1-477F-93F3-99C2741CF827}.Release|Any CPU.Build.0 = Release|Any CPU - {64B1DFC1-B9AC-46D5-951E-7B66EFC47DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {64B1DFC1-B9AC-46D5-951E-7B66EFC47DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {64B1DFC1-B9AC-46D5-951E-7B66EFC47DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {64B1DFC1-B9AC-46D5-951E-7B66EFC47DA6}.Release|Any CPU.Build.0 = Release|Any CPU - {8C97E0F7-5438-4B30-B3F7-DB1757E784C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C97E0F7-5438-4B30-B3F7-DB1757E784C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C97E0F7-5438-4B30-B3F7-DB1757E784C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C97E0F7-5438-4B30-B3F7-DB1757E784C8}.Release|Any CPU.Build.0 = Release|Any CPU - {6DFD9D6C-B52B-44C4-8246-6ACC970A55F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6DFD9D6C-B52B-44C4-8246-6ACC970A55F8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6DFD9D6C-B52B-44C4-8246-6ACC970A55F8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6DFD9D6C-B52B-44C4-8246-6ACC970A55F8}.Release|Any CPU.Build.0 = Release|Any CPU - {B307B77D-47D1-4603-AF04-35F9D5F2BDE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B307B77D-47D1-4603-AF04-35F9D5F2BDE0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B307B77D-47D1-4603-AF04-35F9D5F2BDE0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B307B77D-47D1-4603-AF04-35F9D5F2BDE0}.Release|Any CPU.Build.0 = Release|Any CPU - {906F9E24-D852-44DD-8CB6-9A7EF70A09D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {906F9E24-D852-44DD-8CB6-9A7EF70A09D7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {906F9E24-D852-44DD-8CB6-9A7EF70A09D7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {906F9E24-D852-44DD-8CB6-9A7EF70A09D7}.Release|Any CPU.Build.0 = Release|Any CPU - {C14A7CA4-96DA-498A-B8A9-291AE54A5BD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C14A7CA4-96DA-498A-B8A9-291AE54A5BD5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C14A7CA4-96DA-498A-B8A9-291AE54A5BD5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C14A7CA4-96DA-498A-B8A9-291AE54A5BD5}.Release|Any CPU.Build.0 = Release|Any CPU - {065DF942-2AFF-44A0-AA7A-44CCC5446848}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {065DF942-2AFF-44A0-AA7A-44CCC5446848}.Debug|Any CPU.Build.0 = Debug|Any CPU - {065DF942-2AFF-44A0-AA7A-44CCC5446848}.Release|Any CPU.ActiveCfg = Release|Any CPU - {065DF942-2AFF-44A0-AA7A-44CCC5446848}.Release|Any CPU.Build.0 = Release|Any CPU - {9434774F-B80A-490F-A57A-52031CC2F5C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9434774F-B80A-490F-A57A-52031CC2F5C6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9434774F-B80A-490F-A57A-52031CC2F5C6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9434774F-B80A-490F-A57A-52031CC2F5C6}.Release|Any CPU.Build.0 = Release|Any CPU + {342A1012-23DF-4D2C-9E37-D8B6175C0D55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {342A1012-23DF-4D2C-9E37-D8B6175C0D55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {342A1012-23DF-4D2C-9E37-D8B6175C0D55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {342A1012-23DF-4D2C-9E37-D8B6175C0D55}.Release|Any CPU.Build.0 = Release|Any CPU + {82F1B5A7-7D2E-40B8-9DFE-0B752A00272F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {82F1B5A7-7D2E-40B8-9DFE-0B752A00272F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {82F1B5A7-7D2E-40B8-9DFE-0B752A00272F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {82F1B5A7-7D2E-40B8-9DFE-0B752A00272F}.Release|Any CPU.Build.0 = Release|Any CPU + {4F2C26C6-F0A2-4427-82E9-9619831EEBE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F2C26C6-F0A2-4427-82E9-9619831EEBE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F2C26C6-F0A2-4427-82E9-9619831EEBE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F2C26C6-F0A2-4427-82E9-9619831EEBE0}.Release|Any CPU.Build.0 = Release|Any CPU + {ED518130-CADD-4D9F-8E42-48DBB43DD131}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED518130-CADD-4D9F-8E42-48DBB43DD131}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED518130-CADD-4D9F-8E42-48DBB43DD131}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED518130-CADD-4D9F-8E42-48DBB43DD131}.Release|Any CPU.Build.0 = Release|Any CPU + {793C59B0-7712-49A5-8A49-C1527FCA4080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {793C59B0-7712-49A5-8A49-C1527FCA4080}.Debug|Any CPU.Build.0 = Debug|Any CPU + {793C59B0-7712-49A5-8A49-C1527FCA4080}.Release|Any CPU.ActiveCfg = Release|Any CPU + {793C59B0-7712-49A5-8A49-C1527FCA4080}.Release|Any CPU.Build.0 = Release|Any CPU + {798A8C74-E96E-455D-81DB-AFFBA53140FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {798A8C74-E96E-455D-81DB-AFFBA53140FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {798A8C74-E96E-455D-81DB-AFFBA53140FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {798A8C74-E96E-455D-81DB-AFFBA53140FB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {2D31C66F-9644-49FC-B5F8-3FA3EE49FAC8} + SolutionGuid = {A6CFB064-4E95-4F77-853B-34C8245B775B} EndGlobalSection EndGlobal diff --git a/Lab4/Moderator/Moderator.csproj b/Lab4/Moderator/Moderator.csproj deleted file mode 100644 index ba55bb0..0000000 --- a/Lab4/Moderator/Moderator.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - diff --git a/Lab4/Moderator/ModeratorLogic.cs b/Lab4/Moderator/ModeratorLogic.cs deleted file mode 100644 index 923aa18..0000000 --- a/Lab4/Moderator/ModeratorLogic.cs +++ /dev/null @@ -1,49 +0,0 @@ -using ChatRoomContract; -using NLog; -using Bogus; - -namespace Moderator; - -public class ModeratorLogic -{ - private IChatRoomService chatRoom; - - public ModeratorLogic(IChatRoomService chatRoom) - { - this.chatRoom = chatRoom; - } - - public void Run() - { - Logger log = LogManager.GetCurrentClassLogger(); - - var faker = new Faker("en"); - - var name = faker.Name.FullName(); - int clientId = chatRoom.RegisterClient(name); - log.Info($"Registered with client id {clientId}"); - - Console.Title = $"Moderator | {name} | {clientId}"; - - while (true) - { - var message = chatRoom.GetNewMessage(); - if (message != null) - { - log.Info($"Checking message ({message.id}): {message.contents}"); - Thread.Sleep(500); - - if (message.needsToBeCensored) - { - chatRoom.RejectMessage(message.id); - } - else - { - chatRoom.ApproveMessage(message.id); - } - } - - Thread.Sleep(1 * 1000); - } - } -} diff --git a/Lab4/ModeratorGrpc/Moderator.cs b/Lab4/ModeratorGrpc/Moderator.cs deleted file mode 100644 index 36bf265..0000000 --- a/Lab4/ModeratorGrpc/Moderator.cs +++ /dev/null @@ -1,52 +0,0 @@ -using ChatRoomContract; -using NLog; -using Moderator; - -namespace ModeratorGrpc; - -internal class Moderator -{ - /// - /// Configures logging subsystem. - /// - private static void ConfigureLogging() - { - var config = new NLog.Config.LoggingConfiguration(); - - var console = - new NLog.Targets.ConsoleTarget("console") - { - Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" - }; - config.AddTarget(console); - config.AddRuleForAllLevels(console); - - LogManager.Configuration = config; - } - - static void Main(string[] args) - { - Logger log = LogManager.GetCurrentClassLogger(); - - ConfigureLogging(); - - while (true) - { - var client = new ChatRoomGrpcClient("http://127.0.0.1:5000"); - var moderator = new ModeratorLogic(client); - - try - { - moderator.Run(); - } - catch (Exception e) - { - //log whatever exception to console - log.Warn(e, "Unhandled exception caught. Will restart main loop."); - - //prevent console spamming - Thread.Sleep(2000); - } - } - } -} diff --git a/Lab4/ModeratorGrpc/ModeratorGrpc.csproj b/Lab4/ModeratorGrpc/ModeratorGrpc.csproj deleted file mode 100644 index 80134ec..0000000 --- a/Lab4/ModeratorGrpc/ModeratorGrpc.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net6.0 - enable - enable - - - - - - - - - - - - diff --git a/Lab4/ModeratorRabbitMQ/Moderator.cs b/Lab4/ModeratorRabbitMQ/Moderator.cs deleted file mode 100644 index 66d768a..0000000 --- a/Lab4/ModeratorRabbitMQ/Moderator.cs +++ /dev/null @@ -1,61 +0,0 @@ -using ChatRoomContract; -using NLog; -using Bogus; -using Moderator; - -namespace ModeratorRabbitMQ; - -internal class Moderator -{ - /// - /// Configures logging subsystem. - /// - private static void ConfigureLogging() - { - var config = new NLog.Config.LoggingConfiguration(); - - var console = - new NLog.Targets.ConsoleTarget("console") - { - Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" - }; - config.AddTarget(console); - config.AddRuleForAllLevels(console); - - LogManager.Configuration = config; - } - - /// - /// Entry point - /// - static void Main() - { - Logger log = LogManager.GetCurrentClassLogger(); - - ConfigureLogging(); - - while (true) - { - var chatRoom = new ChatRoomRabbitMQClient( - RabbitMQConfig.CreateConnection(), - RabbitMQConfig.ExchangeName, - RabbitMQConfig.CreateClientQueueName(), - RabbitMQConfig.ServerQueueName - ); - var moderator = new ModeratorLogic(chatRoom); - - try - { - moderator.Run(); - } - catch (Exception e) - { - //log whatever exception to console - log.Warn(e, "Unhandled exception caught. Will restart main loop."); - - //prevent console spamming - Thread.Sleep(2000); - } - } - } -} diff --git a/Lab4/ModeratorRabbitMQ/ModeratorRabbitMQ.csproj b/Lab4/ModeratorRabbitMQ/ModeratorRabbitMQ.csproj deleted file mode 100644 index 80134ec..0000000 --- a/Lab4/ModeratorRabbitMQ/ModeratorRabbitMQ.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net6.0 - enable - enable - - - - - - - - - - - - diff --git a/Lab4/ModeratorRest/Moderator.cs b/Lab4/ModeratorRest/Moderator.cs index c74e336..0c9cffd 100644 --- a/Lab4/ModeratorRest/Moderator.cs +++ b/Lab4/ModeratorRest/Moderator.cs @@ -1,15 +1,20 @@ using ChatRoomContract; using NLog; -using Moderator; +using Bogus; namespace ModeratorRest; internal class Moderator { + /// + /// Logger for this class. + /// + Logger log = LogManager.GetCurrentClassLogger(); + /// /// Configures logging subsystem. /// - private static void ConfigureLogging() + private void ConfigureLogging() { var config = new NLog.Config.LoggingConfiguration(); @@ -24,20 +29,49 @@ internal class Moderator LogManager.Configuration = config; } - static void Main(string[] args) + private void RunConnection(IChatRoomService chatRoom) { - Logger log = LogManager.GetCurrentClassLogger(); + var faker = new Faker("en"); + var name = faker.Name.FullName(); + int clientId = chatRoom.RegisterClient(name); + log.Info($"Registered with client id {clientId}"); + + Console.Title = $"Moderator | {name} | {clientId}"; + + while (true) + { + var message = chatRoom.GetNewMessage(); + if (message != null) + { + log.Info($"Checking message ({message.id}): {message.contents}"); + Thread.Sleep(500); + + if (message.needsToBeCensored) + { + chatRoom.RejectMessage(message.id); + } + else + { + chatRoom.ApproveMessage(message.id); + } + } + + Thread.Sleep(1 * 1000); + } + } + + private void Run() + { ConfigureLogging(); while (true) { - var client = new ChatRoomRestClient("http://127.0.0.1:5000", new HttpClient()); - var moderator = new ModeratorLogic(client); + var client = new RestChatRoomClient("http://127.0.0.1:5001", new HttpClient()); try { - moderator.Run(); + RunConnection(client); } catch (Exception e) { @@ -49,4 +83,10 @@ internal class Moderator } } } + + static void Main(string[] args) + { + var self = new Moderator(); + self.Run(); + } } diff --git a/Lab4/ModeratorRest/ModeratorRest.csproj b/Lab4/ModeratorRest/ModeratorRest.csproj index 80134ec..ac175f5 100644 --- a/Lab4/ModeratorRest/ModeratorRest.csproj +++ b/Lab4/ModeratorRest/ModeratorRest.csproj @@ -8,12 +8,12 @@ + - diff --git a/Lab4/ModeratorSimpleRPC/Moderator.cs b/Lab4/ModeratorSimpleRPC/Moderator.cs deleted file mode 100644 index f362873..0000000 --- a/Lab4/ModeratorSimpleRPC/Moderator.cs +++ /dev/null @@ -1,81 +0,0 @@ -using ChatRoomContract; -using Microsoft.Extensions.DependencyInjection; -using NLog; -using SimpleRpc.Transports.Http.Client; -using SimpleRpc.Serialization.Hyperion; -using SimpleRpc.Transports; -using System.Diagnostics; -using Moderator; - -namespace ModeratorSimpleRPC; - -internal class Moderator -{ - /// - /// Configures logging subsystem. - /// - private static void ConfigureLogging() - { - var config = new NLog.Config.LoggingConfiguration(); - - var console = - new NLog.Targets.ConsoleTarget("console") - { - Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" - }; - config.AddTarget(console); - config.AddRuleForAllLevels(console); - - LogManager.Configuration = config; - } - - static void Main(string[] args) - { - Logger log = LogManager.GetCurrentClassLogger(); - - //configure logging - ConfigureLogging(); - - //initialize random number generator - var rnd = new Random(); - - while (true) - { - //connect to the server, get service client proxy - var sc = new ServiceCollection(); - sc - .AddSimpleRpcClient( - "chatRoomService", //must be same as on line 86 - new HttpClientTransportOptions - { - Url = "http://127.0.0.1:5001/simplerpc", - Serializer = "HyperionMessageSerializer" - } - ) - .AddSimpleRpcHyperionSerializer(); - - sc.AddSimpleRpcProxy("chatRoomService"); //must be same as on line 77 - - var sp = sc.BuildServiceProvider(); - - var chatRoom = sp.GetService(); - Debug.Assert(chatRoom != null); - - var moderator = new ModeratorLogic(chatRoom); - - try - { - moderator.Run(); - } - catch (Exception e) - { - //log whatever exception to console - log.Warn(e, "Unhandled exception caught. Will restart main loop."); - - //prevent console spamming - Thread.Sleep(2000); - } - } - } -} - diff --git a/Lab4/Participant/Participant.csproj b/Lab4/Participant/Participant.csproj deleted file mode 100644 index ba55bb0..0000000 --- a/Lab4/Participant/Participant.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - diff --git a/Lab4/Participant/ParticipantLogic.cs b/Lab4/Participant/ParticipantLogic.cs deleted file mode 100644 index 303f2a9..0000000 --- a/Lab4/Participant/ParticipantLogic.cs +++ /dev/null @@ -1,54 +0,0 @@ -using ChatRoomContract; -using Bogus; -using NLog; - -namespace Participant; - -public class ParticipantLogic -{ - private IChatRoomService chatRoom; - - public ParticipantLogic(IChatRoomService chatRoom) - { - this.chatRoom = chatRoom; - } - - public void Run() - { - Logger log = LogManager.GetCurrentClassLogger(); - - var faker = new Faker("en"); - var rnd = new Random(); - - var name = faker.Name.FullName(); - int clientId = chatRoom.RegisterClient(name); - log.Info($"Registered with client id {clientId}"); - - while (true) - { - int strikes = chatRoom.GetStrikes(clientId); - Console.Title = $"Participant | {name} | {clientId} | {strikes} Strikes"; - - var message = string.Join(" ", faker.Lorem.Words(5)); - bool needsToBeCensored = rnd.Next(0, 100) > 50; - if (chatRoom.SendMessage(clientId, message, needsToBeCensored)) - { - log.Info("Sent message"); - } - else - { - log.Info("Failed to send message, blocked"); - var blockedUntil = chatRoom.GetBlockedUntil(clientId); - var now = DateTime.UtcNow; - if (blockedUntil != null && blockedUntil > now) - { - var delta = blockedUntil.Value - now; - log.Info($"Waiting {delta.TotalSeconds:F3}s until block expires"); - Thread.Sleep((int)delta.TotalMilliseconds); - } - } - - Thread.Sleep(2 * 1000); - } - } -} diff --git a/Lab4/ParticipantGrpc/Participant.cs b/Lab4/ParticipantGrpc/Participant.cs index 77f5e5f..486bd89 100644 --- a/Lab4/ParticipantGrpc/Participant.cs +++ b/Lab4/ParticipantGrpc/Participant.cs @@ -1,16 +1,20 @@ using ChatRoomContract; using NLog; using Bogus; -using Participant; -namespace ParticipantGrpc; +namespace Participant; internal class Participant { + /// + /// Logger for this class. + /// + Logger log = LogManager.GetCurrentClassLogger(); + /// /// Configures logging subsystem. /// - private static void ConfigureLogging() + private void ConfigureLogging() { var config = new NLog.Config.LoggingConfiguration(); @@ -25,20 +29,54 @@ internal class Participant LogManager.Configuration = config; } - static void Main(string[] args) + private void RunConnection(IChatRoomService chatRoom) { - Logger log = LogManager.GetCurrentClassLogger(); + var faker = new Faker("en"); + var rnd = new Random(); + var name = faker.Name.FullName(); + int clientId = chatRoom.RegisterClient(name); + log.Info($"Registered with client id {clientId}"); + + while (true) + { + int strikes = chatRoom.GetStrikes(clientId); + Console.Title = $"Participant | {name} | {clientId} | {strikes} Strikes"; + + var message = string.Join(" ", faker.Lorem.Words(5)); + bool needsToBeCensored = rnd.Next(0, 100) > 50; + if (chatRoom.SendMessage(clientId, message, needsToBeCensored)) + { + log.Info("Sent message"); + } + else + { + log.Info("Failed to send message, blocked"); + var blockedUntil = chatRoom.GetBlockedUntil(clientId); + var now = DateTime.UtcNow; + if (blockedUntil != null && blockedUntil > now) + { + var delta = blockedUntil.Value - now; + log.Info($"Waiting {delta.TotalSeconds:F3}s until block expires"); + Thread.Sleep((int)delta.TotalMilliseconds); + } + } + + Thread.Sleep(2 * 1000); + } + } + + private void Run() + { ConfigureLogging(); while (true) { - var client = new ChatRoomGrpcClient("http://127.0.0.1:5000"); - var participant = new ParticipantLogic(client); + var client = new GrpcChatRoomClient("http://127.0.0.1:5002"); try { - participant.Run(); + RunConnection(client); } catch (Exception e) { @@ -50,4 +88,10 @@ internal class Participant } } } + + static void Main(string[] args) + { + var self = new Participant(); + self.Run(); + } } diff --git a/Lab4/ParticipantGrpc/ParticipantGrpc.csproj b/Lab4/ParticipantGrpc/ParticipantGrpc.csproj index bdbcc8a..ac175f5 100644 --- a/Lab4/ParticipantGrpc/ParticipantGrpc.csproj +++ b/Lab4/ParticipantGrpc/ParticipantGrpc.csproj @@ -8,12 +8,12 @@ + - diff --git a/Lab4/ParticipantRabbitMQ/Participant.cs b/Lab4/ParticipantRabbitMQ/Participant.cs deleted file mode 100644 index d94e84c..0000000 --- a/Lab4/ParticipantRabbitMQ/Participant.cs +++ /dev/null @@ -1,60 +0,0 @@ -using ChatRoomContract; -using NLog; -using Participant; - -namespace ParticipantRabbitMQ; - -internal class Participant -{ - /// - /// Configures logging subsystem. - /// - private static void ConfigureLogging() - { - var config = new NLog.Config.LoggingConfiguration(); - - var console = - new NLog.Targets.ConsoleTarget("console") - { - Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" - }; - config.AddTarget(console); - config.AddRuleForAllLevels(console); - - LogManager.Configuration = config; - } - - /// - /// Entry point - /// - static void Main() - { - Logger log = LogManager.GetCurrentClassLogger(); - - ConfigureLogging(); - - while (true) - { - var chatRoom = new ChatRoomRabbitMQClient( - RabbitMQConfig.CreateConnection(), - RabbitMQConfig.ExchangeName, - RabbitMQConfig.CreateClientQueueName(), - RabbitMQConfig.ServerQueueName - ); - var participant = new ParticipantLogic(chatRoom); - - try - { - participant.Run(); - } - catch (Exception e) - { - //log whatever exception to console - log.Warn(e, "Unhandled exception caught. Will restart main loop."); - - //prevent console spamming - Thread.Sleep(2000); - } - } - } -} diff --git a/Lab4/ParticipantRabbitMQ/ParticipantRabbitMQ.csproj b/Lab4/ParticipantRabbitMQ/ParticipantRabbitMQ.csproj deleted file mode 100644 index bdbcc8a..0000000 --- a/Lab4/ParticipantRabbitMQ/ParticipantRabbitMQ.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net6.0 - enable - enable - - - - - - - - - - - - diff --git a/Lab4/ParticipantRest/Participant.cs b/Lab4/ParticipantRest/Participant.cs deleted file mode 100644 index 35e239d..0000000 --- a/Lab4/ParticipantRest/Participant.cs +++ /dev/null @@ -1,52 +0,0 @@ -using ChatRoomContract; -using NLog; -using Participant; - -namespace ParticipantRest; - -internal class Participant -{ - /// - /// Configures logging subsystem. - /// - private static void ConfigureLogging() - { - var config = new NLog.Config.LoggingConfiguration(); - - var console = - new NLog.Targets.ConsoleTarget("console") - { - Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" - }; - config.AddTarget(console); - config.AddRuleForAllLevels(console); - - LogManager.Configuration = config; - } - - static void Main(string[] args) - { - Logger log = LogManager.GetCurrentClassLogger(); - - ConfigureLogging(); - - while (true) - { - var client = new ChatRoomRestClient("http://127.0.0.1:5000", new HttpClient()); - var participant = new ParticipantLogic(client); - - try - { - participant.Run(); - } - catch (Exception e) - { - //log whatever exception to console - log.Warn(e, "Unhandled exception caught. Will restart main loop."); - - //prevent console spamming - Thread.Sleep(2000); - } - } - } -} diff --git a/Lab4/ParticipantRest/ParticipantRest.csproj b/Lab4/ParticipantRest/ParticipantRest.csproj deleted file mode 100644 index bdbcc8a..0000000 --- a/Lab4/ParticipantRest/ParticipantRest.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net6.0 - enable - enable - - - - - - - - - - - - diff --git a/Lab4/ParticipantSimpleRPC/Participant.cs b/Lab4/ParticipantSimpleRPC/Participant.cs deleted file mode 100644 index f1c9bae..0000000 --- a/Lab4/ParticipantSimpleRPC/Participant.cs +++ /dev/null @@ -1,81 +0,0 @@ -using ChatRoomContract; -using Microsoft.Extensions.DependencyInjection; -using NLog; -using SimpleRpc.Transports.Http.Client; -using SimpleRpc.Serialization.Hyperion; -using SimpleRpc.Transports; -using System.Diagnostics; -using Participant; - -namespace ParticipantSimpleRPC; - -internal class Participant -{ - /// - /// Configures logging subsystem. - /// - private static void ConfigureLogging() - { - var config = new NLog.Config.LoggingConfiguration(); - - var console = - new NLog.Targets.ConsoleTarget("console") - { - Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" - }; - config.AddTarget(console); - config.AddRuleForAllLevels(console); - - LogManager.Configuration = config; - } - - static void Main(string[] args) - { - Logger log = LogManager.GetCurrentClassLogger(); - - //configure logging - ConfigureLogging(); - - //initialize random number generator - var rnd = new Random(); - - while (true) - { - //connect to the server, get service client proxy - var sc = new ServiceCollection(); - sc - .AddSimpleRpcClient( - "chatRoomService", //must be same as on line 86 - new HttpClientTransportOptions - { - Url = "http://127.0.0.1:5001/simplerpc", - Serializer = "HyperionMessageSerializer" - } - ) - .AddSimpleRpcHyperionSerializer(); - - sc.AddSimpleRpcProxy("chatRoomService"); //must be same as on line 77 - - var sp = sc.BuildServiceProvider(); - - var chatRoom = sp.GetService(); - Debug.Assert(chatRoom != null); - - var participant = new ParticipantLogic(chatRoom); - - try - { - participant.Run(); - } - catch (Exception e) - { - //log whatever exception to console - log.Warn(e, "Unhandled exception caught. Will restart main loop."); - - //prevent console spamming - Thread.Sleep(2000); - } - } - } -} - diff --git a/Lab4/ChatRoom/ChatRoomRestController.cs b/Lab4/RestToSimpleRPCAdapter/ChatRoomController.cs similarity index 82% rename from Lab4/ChatRoom/ChatRoomRestController.cs rename to Lab4/RestToSimpleRPCAdapter/ChatRoomController.cs index 86fd6af..31b90db 100644 --- a/Lab4/ChatRoom/ChatRoomRestController.cs +++ b/Lab4/RestToSimpleRPCAdapter/ChatRoomController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc; +using ChatRoomContract; +using Microsoft.AspNetCore.Mvc; namespace ChatRoom; @@ -9,20 +10,20 @@ namespace ChatRoom; /// [Route("chatRoom")] [ApiController] -public class ChatRoomRestController : ControllerBase +public class ChatRoomController : ControllerBase { /// /// Service logic. This is created in Server.StartServer() and received through DI in constructor. /// - private readonly ChatRoomLogic logic; + private readonly IChatRoomService service; /// /// Constructor /// /// Logic to use. This will get passed through DI. - public ChatRoomRestController(ChatRoomLogic logic) + public ChatRoomController(IChatRoomService service) { - this.logic = logic; + this.service = service; } /// @@ -33,7 +34,7 @@ public class ChatRoomRestController : ControllerBase [HttpPost("/registerClient")] public ActionResult RegisterClient(string name) { - return logic.RegisterClient(name); + return service.RegisterClient(name); } /// @@ -44,7 +45,7 @@ public class ChatRoomRestController : ControllerBase [HttpGet("/getStrikes")] public ActionResult GetStrikes(int clientId) { - return logic.GetStrikes(clientId); + return service.GetStrikes(clientId); } /// @@ -55,7 +56,7 @@ public class ChatRoomRestController : ControllerBase [HttpGet("/getBlockedUntil")] public ActionResult GetBlockedUntil(int clientId) { - return logic.GetBlockedUntil(clientId); + return service.GetBlockedUntil(clientId); } /// @@ -68,7 +69,7 @@ public class ChatRoomRestController : ControllerBase [HttpPost("/sendMessage")] public ActionResult SendMessage(int clientId, string contents, bool needsToBeCensored) { - return logic.SendMessage(clientId, contents, needsToBeCensored); + return service.SendMessage(clientId, contents, needsToBeCensored); } /// @@ -78,7 +79,7 @@ public class ChatRoomRestController : ControllerBase [HttpGet("/getNewMessage")] public ActionResult GetNewMessage() { - return logic.GetNewMessage(); + return service.GetNewMessage(); } /// @@ -88,7 +89,7 @@ public class ChatRoomRestController : ControllerBase [HttpPost("/rejectMessage")] public void RejectMessage(int messageId) { - logic.RejectMessage(messageId); + service.RejectMessage(messageId); } /// @@ -98,6 +99,6 @@ public class ChatRoomRestController : ControllerBase [HttpPost("/approveMessage")] public void ApproveMessage(int messageId) { - logic.ApproveMessage(messageId); + service.ApproveMessage(messageId); } } diff --git a/Lab4/RestToSimpleRPCAdapter/Properties/launchSettings.json b/Lab4/RestToSimpleRPCAdapter/Properties/launchSettings.json new file mode 100644 index 0000000..43f7e1d --- /dev/null +++ b/Lab4/RestToSimpleRPCAdapter/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "ChatRoom": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:55035;http://localhost:55036" + } + } +} \ No newline at end of file diff --git a/Lab4/ChatRoom/ChatRoom.csproj b/Lab4/RestToSimpleRPCAdapter/RestToSimpleRPCAdapter.csproj similarity index 81% rename from Lab4/ChatRoom/ChatRoom.csproj rename to Lab4/RestToSimpleRPCAdapter/RestToSimpleRPCAdapter.csproj index cf8505e..027bace 100644 --- a/Lab4/ChatRoom/ChatRoom.csproj +++ b/Lab4/RestToSimpleRPCAdapter/RestToSimpleRPCAdapter.csproj @@ -4,15 +4,13 @@ net6.0 enable enable - True - - + diff --git a/Lab4/RestToSimpleRPCAdapter/Server.cs b/Lab4/RestToSimpleRPCAdapter/Server.cs new file mode 100644 index 0000000..f9830ee --- /dev/null +++ b/Lab4/RestToSimpleRPCAdapter/Server.cs @@ -0,0 +1,147 @@ +using Microsoft.Extensions.Logging; +using System.Net; +using System.Text.Json.Serialization; +using NLog; +using ChatRoomContract; +using System.Diagnostics; +using SimpleRpc.Transports; +using SimpleRpc.Transports.Http.Client; +using SimpleRpc.Serialization.Hyperion; + +namespace RestToSimpleRPCAdapter; + +public class Server +{ + /// + /// Logger for this class. + /// + Logger log = LogManager.GetCurrentClassLogger(); + + /// + /// Program entry point. + /// + /// Command line arguments. + public static void Main(string[] args) + { + var self = new Server(); + self.Run(args); + } + + /// + /// Program body. + /// + /// Command line arguments. + private void Run(string[] args) + { + //configure logging + ConfigureLogging(); + + //indicate server is about to start + log.Info("Server is about to start"); + + //start the server + StartServer(args); + } + + /// + /// Configure loggin subsystem. + /// + private void ConfigureLogging() + { + var config = new NLog.Config.LoggingConfiguration(); + + var console = + new NLog.Targets.ConsoleTarget("console") + { + Layout = @"${date:format=HH\:mm\:ss}|${level}| ${message} ${exception}" + }; + config.AddTarget(console); + config.AddRuleForAllLevels(console); + + LogManager.Configuration = config; + } + + public IChatRoomService getSimpleRPCService() + { + //connect to the server, get service client proxy + var sc = new ServiceCollection(); + sc + .AddSimpleRpcClient( + "chatRoomService", //must be same as on line 86 + new HttpClientTransportOptions + { + Url = "http://127.0.0.1:5000/simplerpc", + Serializer = "HyperionMessageSerializer" + } + ) + .AddSimpleRpcHyperionSerializer(); + + sc.AddSimpleRpcProxy("chatRoomService"); //must be same as on line 77 + + var sp = sc.BuildServiceProvider(); + + var chatRoom = sp.GetService(); + Debug.Assert(chatRoom != null); + + return chatRoom; + } + + /// + /// Starts integrated server. + /// + /// Command line arguments. + public void StartServer(string[] args) + { + //create web app builder + var builder = WebApplication.CreateBuilder(args); + + //configure integrated server + builder.WebHost.ConfigureKestrel(opts => + { + opts.Listen(IPAddress.Loopback, 5001); + }); + + //turn on support for web api controllers + builder.Services + .AddControllers() + .AddJsonOptions(opts => + { + //this makes enumeration values to be strings instead of integers in opeanapi doc + opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + + //add CORS policies + builder.Services.AddCors(cr => + { + //allow everything from everywhere + cr.AddPolicy("allowAll", cp => + { + cp.AllowAnyOrigin(); + cp.AllowAnyMethod(); + cp.AllowAnyHeader(); + }); + }); + + //publish the background logic as (an internal) service through dependency injection, + //otherwise it will not start until the first client calls into controller + builder.Services.AddSingleton(getSimpleRPCService()); + + //build the server + var app = builder.Build(); + + //turn CORS policy on + app.UseCors("allowAll"); + + //turn on request routing + app.UseRouting(); + + //configure routes + app.MapControllerRoute( + name: "default", + pattern: "{controller}/{action=Index}/{id?}" + ); + + //run the server + app.Run(); + } +} diff --git a/Lab4/RestToSimpleRPCAdapter/appsettings.json b/Lab4/RestToSimpleRPCAdapter/appsettings.json new file mode 100644 index 0000000..ae459eb --- /dev/null +++ b/Lab4/RestToSimpleRPCAdapter/appsettings.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "Microsoft.AspNetCore.Hosting.Diagnostics": "Warning" + } + }, + "AllowedHosts": "*" +}