├── .gitignore ├── ConsoleServer ├── App.config ├── ArgsParser.cs ├── ConsoleServer.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── Engine ├── Api │ ├── Client │ │ ├── Admin │ │ │ └── ClientSendAdminAction.cs │ │ ├── ClientApi.cs │ │ ├── ClientCommand.cs │ │ ├── ClientCommandId.cs │ │ ├── Files │ │ │ ├── ClientAddFileAction.cs │ │ │ ├── ClientDownloadFileAction.cs │ │ │ ├── ClientFilePostedCommand.cs │ │ │ ├── ClientFileRemovedCommand.cs │ │ │ ├── ClientReadFilePartCommand.cs │ │ │ ├── ClientRemoveFileAction.cs │ │ │ └── ClientWriteFilePartCommand.cs │ │ ├── Messages │ │ │ ├── ClientOutPrivateMessageCommand.cs │ │ │ ├── ClientOutRoomMessageCommand.cs │ │ │ ├── ClientOutSystemMessageCommand.cs │ │ │ ├── ClientRemoveMessagesCommand.cs │ │ │ ├── ClientSendMessageAction.cs │ │ │ └── ClientSendPrivateMessageAction.cs │ │ ├── Others │ │ │ ├── ClientEmptyCommand.cs │ │ │ └── ClientPingResponseCommand.cs │ │ ├── P2P │ │ │ ├── ClientConnectToP2PServiceCommand.cs │ │ │ ├── ClientConnectToPeerAction.cs │ │ │ ├── ClientConnectToPeerCommand.cs │ │ │ └── ClientWaitPeerConnectionCommand.cs │ │ ├── Registrations │ │ │ ├── ClientRegisterAction.cs │ │ │ ├── ClientRegistrationResponseCommand.cs │ │ │ └── ClientUnregistrerAction.cs │ │ ├── Rooms │ │ │ ├── ClientCreateRoomAction.cs │ │ │ ├── ClientDeleteRoomAction.cs │ │ │ ├── ClientExitFromRoomAction.cs │ │ │ ├── ClientInviteUsersAction.cs │ │ │ ├── ClientKickUsersAction.cs │ │ │ ├── ClientRefreshRoomAction.cs │ │ │ ├── ClientRoomClosedCommand.cs │ │ │ ├── ClientRoomOpenedCommand.cs │ │ │ ├── ClientRoomRefreshedCommand.cs │ │ │ └── ClientSetRoomAdminAction.cs │ │ └── Voice │ │ │ └── ClientPlayVoiceCommand.cs │ ├── IAction.cs │ ├── IApi.cs │ ├── ICommand.cs │ └── Server │ │ ├── Admin │ │ └── ServerAdminCommand.cs │ │ ├── Files │ │ ├── ServerAddFileToRoomCommand.cs │ │ └── ServerRemoveFileFromRoomCommand.cs │ │ ├── Messages │ │ ├── ServerRemoveMessagesAction.cs │ │ ├── ServerSendRoomMessageCommand.cs │ │ └── ServerSendSystemMessageAction.cs │ │ ├── Others │ │ ├── ServerEmptyCommand.cs │ │ └── ServerPingRequestCommand.cs │ │ ├── P2P │ │ ├── ServerIntroduceConnectionsAction.cs │ │ ├── ServerP2PConnectRequestCommand.cs │ │ ├── ServerP2PReadyAcceptCommand.cs │ │ └── ServerSendP2PConnectRequestAction.cs │ │ ├── Registrations │ │ ├── ServerRegisterCommand.cs │ │ ├── ServerRemoveUserAction.cs │ │ └── ServerUnregisterCommand.cs │ │ ├── Rooms │ │ ├── ServerCreateRoomCommand.cs │ │ ├── ServerDeleteRoomCommand.cs │ │ ├── ServerExitFromRoomCommand.cs │ │ ├── ServerInviteUsersCommand.cs │ │ ├── ServerKickUsersCommand.cs │ │ ├── ServerRefreshRoomCommand.cs │ │ └── ServerSetRoomAdminCommand.cs │ │ ├── ServerApi.cs │ │ ├── ServerCommand.cs │ │ └── ServerCommandId.cs ├── Audio │ ├── IPlayer.cs │ ├── IRecorder.cs │ └── OpenAL │ │ ├── OpenALPlayer.cs │ │ └── OpenALRecorder.cs ├── Engine.csproj ├── EngineStrongName.snk ├── EventArgs │ ├── AsyncErrorEventArgs.cs │ ├── ConnectEventArgs.cs │ ├── ConnectionEventArgs.cs │ ├── FileDownloadEventArgs.cs │ ├── PackageReceivedEventArgs.cs │ ├── PackageSendedEventArgs.cs │ ├── PluginEventArgs.cs │ ├── ReceiveMessageEventArgs.cs │ ├── RecordedEventArgs.cs │ ├── RegistrationEventArgs.cs │ ├── RoomClosedEventArgs.cs │ ├── RoomOpenedEventArgs.cs │ ├── RoomRefreshedEventArgs.cs │ ├── RoomUsersEventArgs.cs │ └── TrustedCertificatesEventArgs.cs ├── Exceptions │ ├── ErrorCode.cs │ └── ModelException.cs ├── Helpers │ ├── CertificateGenerator.cs │ ├── Crypter.cs │ ├── EngineSyncContext.cs │ ├── EventDispatcher.cs │ ├── Logger.cs │ ├── Serializer.cs │ └── TryLock.cs ├── Model │ ├── Client │ │ ├── ClientCertificatesStorage.cs │ │ ├── ClientGuard.cs │ │ ├── ClientInitializer.cs │ │ ├── ClientModel.cs │ │ ├── ClientNotifier.cs │ │ └── Entities │ │ │ ├── ClientChat.cs │ │ │ ├── ClientRoom.cs │ │ │ ├── ClientUser.cs │ │ │ └── ClientVoiceRoom.cs │ ├── Common │ │ ├── CertificatesStorage.cs │ │ ├── Dto │ │ │ ├── BinNullable.cs │ │ │ ├── ColorDto.cs │ │ │ ├── FileDescriptionDto.cs │ │ │ ├── MessageDto.cs │ │ │ ├── RoomDto.cs │ │ │ └── UserDto.cs │ │ ├── Entities │ │ │ ├── AudioQuality.cs │ │ │ ├── Chat.cs │ │ │ ├── DownloadingFile.cs │ │ │ ├── FileDescription.cs │ │ │ ├── FileId.cs │ │ │ ├── Message.cs │ │ │ ├── PostedFile.cs │ │ │ ├── Room.cs │ │ │ ├── RoomType.cs │ │ │ ├── SoundPack.cs │ │ │ ├── SystemMessageId.cs │ │ │ ├── User.cs │ │ │ ├── UserId.cs │ │ │ └── VoiceRoom.cs │ │ ├── Guard.cs │ │ ├── Notifier.cs │ │ └── NotifierGenerator.cs │ └── Server │ │ ├── Entities │ │ ├── ServerChat.cs │ │ ├── ServerRoom.cs │ │ └── ServerVoiceRoom.cs │ │ ├── ServerGuard.cs │ │ ├── ServerInitializer.cs │ │ ├── ServerModel.cs │ │ └── ServerNotifier.cs ├── Network │ ├── AsyncClient.cs │ ├── AsyncPeer.cs │ ├── AsyncServer.cs │ ├── CertificateStatus.cs │ ├── Connection.cs │ ├── ConnectionInfo.cs │ ├── P2PService.cs │ ├── Package.cs │ ├── Packed.cs │ ├── Packer.cs │ ├── Pool.cs │ ├── RequestQueue.cs │ ├── ServerBans.cs │ ├── ServerConnection.cs │ └── Unpacked.cs ├── Plugins │ ├── Client │ │ ├── ClientModelWrapper.cs │ │ ├── ClientPlugin.cs │ │ ├── ClientPluginCommand.cs │ │ └── ClientPluginManager.cs │ ├── CrossDomainObject.cs │ ├── Plugin.cs │ ├── PluginInfo.cs │ ├── PluginInfoLoader.cs │ ├── PluginManager.cs │ └── Server │ │ ├── ServerModelWrapper.cs │ │ ├── ServerPlugin.cs │ │ ├── ServerPluginCommand.cs │ │ └── ServerPluginManager.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── LICENSE ├── Libraries └── OpenAL.dll ├── Lidgren.Network ├── Documentation │ ├── ChangedFromV2.txt │ ├── Discovery.html │ ├── Improvements.txt │ ├── PacketLayout.txt │ ├── SimulatingBadNetwork.html │ ├── TODO.txt │ └── Tutorial.html ├── Encryption │ ├── INetEncryption.cs │ ├── NetAESEncryption.cs │ ├── NetBlockEncryptionBase.cs │ ├── NetDESEncryption.cs │ ├── NetRC2Encryption.cs │ ├── NetTripleDESEncryption.cs │ ├── NetXorEncryption.cs │ └── NetXteaEncryption.cs ├── Lidgren.Network.csproj ├── LidgrenNetworkStrongName.snk ├── NamespaceDoc.cs ├── NetBigInteger.cs ├── NetBitVector.cs ├── NetBitWriter.cs ├── NetBuffer.Peek.cs ├── NetBuffer.Read.Reflection.cs ├── NetBuffer.Read.cs ├── NetBuffer.Write.Reflection.cs ├── NetBuffer.Write.cs ├── NetBuffer.cs ├── NetClient.cs ├── NetConnection.Handshake.cs ├── NetConnection.Latency.cs ├── NetConnection.MTU.cs ├── NetConnection.cs ├── NetConnectionStatistics.cs ├── NetConnectionStatus.cs ├── NetConstants.cs ├── NetDeliveryMethod.cs ├── NetException.cs ├── NetFragmentationHelper.cs ├── NetFragmentationInfo.cs ├── NetIncomingMessage.cs ├── NetIncomingMessageType.cs ├── NetMessageType.cs ├── NetNatIntroduction.cs ├── NetOutgoingMessage.cs ├── NetPeer.Discovery.cs ├── NetPeer.Fragmentation.cs ├── NetPeer.Internal.cs ├── NetPeer.LatencySimulation.cs ├── NetPeer.Logging.cs ├── NetPeer.MessagePools.cs ├── NetPeer.Send.cs ├── NetPeer.cs ├── NetPeerConfiguration.cs ├── NetPeerStatistics.cs ├── NetPeerStatus.cs ├── NetQueue.cs ├── NetRandom.cs ├── NetReceiverChannelBase.cs ├── NetReliableOrderedReceiver.cs ├── NetReliableSenderChannel.cs ├── NetReliableSequencedReceiver.cs ├── NetReliableUnorderedReceiver.cs ├── NetSRP.cs ├── NetSendResult.cs ├── NetSenderChannelBase.cs ├── NetServer.cs ├── NetStoredReliableMessage.cs ├── NetTime.cs ├── NetTuple.cs ├── NetUPnP.cs ├── NetUnreliableSenderChannel.cs ├── NetUnreliableSequencedReceiver.cs ├── NetUnreliableUnorderedReceiver.cs ├── NetUtility.cs ├── Properties │ └── AssemblyInfo.cs └── SenderChannelBase.cs ├── README.md ├── ServerCertificate.cer ├── TCPChat.sln ├── UI ├── App.config ├── App.xaml ├── App.xaml.cs ├── Dialogs │ ├── AboutProgramDialog.xaml │ ├── AboutProgramDialog.xaml.cs │ ├── ConnectDialog.xaml │ ├── ConnectDialog.xaml.cs │ ├── CreateRoomDialog.xaml │ ├── CreateRoomDialog.xaml.cs │ ├── GenerateCertificateDialog.xaml │ ├── GenerateCertificateDialog.xaml.cs │ ├── ServerCertificateConfirmDialog.xaml │ ├── ServerCertificateConfirmDialog.xaml.cs │ ├── ServerDialog.xaml │ ├── ServerDialog.xaml.cs │ ├── UsersOperationDialog.xaml │ └── UsersOperationDialog.xaml.cs ├── Images │ ├── chat.ico │ ├── chat.png │ ├── checked.png │ ├── checkedNotMatch.png │ ├── notChecked.png │ ├── voiceOff.png │ ├── voiceOn.png │ └── voiceSpeak.png ├── Infrastructure │ ├── AttachedHelper.cs │ ├── BoolToVisibilityConverter.cs │ ├── Command.cs │ ├── IconToImageSourceConverter.cs │ ├── KeyBoard.cs │ ├── Localized.cs │ ├── Localizer.cs │ ├── LocalizerStorage.cs │ ├── PluginSetting.cs │ ├── RgbToColorConverter.cs │ └── Settings.cs ├── Localization │ ├── Localization.en-US.xml │ ├── Localization.fr-FR.xml │ └── Localization.ru-RU.xml ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Settings.xml ├── UI.csproj ├── UI.csproj.user ├── UIStrongName.snk ├── View │ ├── MainView.xaml │ ├── MainView.xaml.cs │ ├── PostedFilesView.xaml │ ├── PostedFilesView.xaml.cs │ ├── SettingsView.xaml │ └── SettingsView.xaml.cs └── ViewModel │ ├── AudioTabViewModel.cs │ ├── BaseViewModel.cs │ ├── ClientTabViewModel.cs │ ├── LightUserViewModel.cs │ ├── MainViewModel.cs │ ├── MessageViewModel.cs │ ├── PluginInfoViewModel.cs │ ├── PluginSettingTabViewModel.cs │ ├── PluginViewModel.cs │ ├── PostedFilesViewModel.cs │ ├── RoomViewModel.cs │ ├── ServerTabViewModel.cs │ ├── SettingsTabViewModel.cs │ ├── SettingsViewModel.cs │ ├── UiCertificateStatus.cs │ └── UserViewModel.cs └── screen.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Oo]bj/ 3 | [Bb]in/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # Vs folder 12 | .vs/ 13 | 14 | # User-specific files 15 | *.suo 16 | *.user 17 | *.sln.docstates 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Rr]elase/ 22 | x64/ 23 | *_i.c 24 | *_p.c 25 | *.ilk 26 | *.meta 27 | *.obj 28 | *.pch 29 | *.pdb 30 | *.pgc 31 | *.pgd 32 | *.rsp 33 | *.sbr 34 | *.tlb 35 | *.tli 36 | *.tlh 37 | *.tmp 38 | *.log 39 | *.vspscc 40 | *.vssscc 41 | .builds 42 | 43 | # Visual C++ cache files 44 | ipch/ 45 | *.aps 46 | *.ncb 47 | *.opensdf 48 | *.sdf 49 | 50 | # Visual Studio profiler 51 | *.psess 52 | *.vsp 53 | *.vspx 54 | 55 | # Guidance Automation Toolkit 56 | *.gpState 57 | 58 | # ReSharper is a .NET coding add-in 59 | _ReSharper* 60 | 61 | # NCrunch 62 | *.ncrunch* 63 | .*crunch*.local.xml 64 | 65 | # Installshield output folder 66 | [Ee]xpress 67 | 68 | # DocProject is a documentation generator add-in 69 | DocProject/buildhelp/ 70 | DocProject/Help/*.HxT 71 | DocProject/Help/*.HxC 72 | DocProject/Help/*.hhc 73 | DocProject/Help/*.hhk 74 | DocProject/Help/*.hhp 75 | DocProject/Help/Html2 76 | DocProject/Help/html 77 | 78 | # Click-Once directory 79 | publish 80 | 81 | # Publish Web Output 82 | *.Publish.xml 83 | 84 | # NuGet Packages Directory 85 | packages 86 | 87 | # Windows Azure Build Output 88 | csx 89 | *.build.csdef 90 | 91 | # Windows Store app package directory 92 | AppPackages/ 93 | 94 | # Others 95 | [Oo]bj 96 | [Bb]in 97 | sql 98 | TestResults 99 | [Tt]est[Rr]esult* 100 | *.Cache 101 | ClientBin 102 | [Ss]tyle[Cc]op.* 103 | ~$* 104 | *.dbmdl 105 | Generated_Code #added for RIA/Silverlight projects 106 | 107 | # Backup & report files from converting an old project file to a newer 108 | # Visual Studio version. Backup files are not needed, because we have git ;-) 109 | _UpgradeReport_Files/ 110 | Backup*/ 111 | UpgradeLog*.XML 112 | -------------------------------------------------------------------------------- /ConsoleServer/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ConsoleServer/ArgsParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace ConsoleServer 5 | { 6 | public class ArgsParser 7 | { 8 | public delegate bool TryParse(string str, out T value); 9 | 10 | private Dictionary _params; 11 | private Action _fallback; 12 | 13 | public ArgsParser(string[] args, Action fallback) 14 | { 15 | if (args.Length % 2 != 0) 16 | throw new InvalidOperationException("invalid args count"); 17 | 18 | _params = new Dictionary(StringComparer.OrdinalIgnoreCase); 19 | for (int i = 0; i < args.Length; i += 2) 20 | _params.Add(args[i], args[i + 1]); 21 | 22 | _fallback = fallback; 23 | } 24 | 25 | public string GetOrDefault(string key, string def) 26 | { 27 | if (!_params.TryGetValue(key, out string value)) 28 | return def; 29 | return value; 30 | } 31 | 32 | public T GetOrDefault(string key, TryParse parser, T def) 33 | { 34 | var valueStr = GetOrDefault(key, null); 35 | if (valueStr == null) 36 | return def; 37 | 38 | if (!parser(valueStr, out T value)) 39 | return def; 40 | return value; 41 | } 42 | 43 | public string Get(string key) 44 | { 45 | if (!_params.TryGetValue(key, out string value)) 46 | throw CallFallbackAndCreateException("Param not found: " + key); 47 | return value; 48 | } 49 | 50 | public T Get(string key, TryParse parser) 51 | { 52 | var valueStr = Get(key); 53 | if (!parser(valueStr, out T value)) 54 | throw CallFallbackAndCreateException("Can't cast " + key + " to " + typeof(T).Name); 55 | return value; 56 | } 57 | 58 | private Exception CallFallbackAndCreateException(string message) 59 | { 60 | _fallback(); 61 | return new InvalidOperationException(message); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ConsoleServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("ConsoleServer")] 8 | [assembly: AssemblyDescription("TCPChat Console server")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("39-80")] 11 | [assembly: AssemblyProduct("ConsoleServer")] 12 | [assembly: AssemblyCopyright("Copyright © 39-80 2018")] 13 | [assembly: AssemblyTrademark("ThirtyNineEighty")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("41808c4f-3625-424a-b85b-fada4af3239a")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("5.1.0.0")] 35 | [assembly: AssemblyFileVersion("5.1.0.0")] 36 | -------------------------------------------------------------------------------- /Engine/Api/Client/Admin/ClientSendAdminAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Admin; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api.Client.Admin 7 | { 8 | [Serializable] 9 | public class ClientSendAdminAction : IAction 10 | { 11 | private readonly string _password; 12 | private readonly string _textCommand; 13 | 14 | [SecuritySafeCritical] 15 | public ClientSendAdminAction(string password, string textCommand) 16 | { 17 | if (!ServerAdminCommand.IsTextCommand(textCommand)) 18 | throw new ArgumentException("this is not a text command"); 19 | 20 | _password = password; 21 | _textCommand = textCommand; 22 | } 23 | 24 | [SecuritySafeCritical] 25 | public void Perform() 26 | { 27 | var messageContent = new ServerAdminCommand.MessageContent { Password = _password, TextCommand = _textCommand }; 28 | ClientModel.Client.SendMessage(ServerAdminCommand.CommandId, messageContent); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Engine/Api/Client/ClientCommandId.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Api.Client 2 | { 3 | // TODO: rus 4 | //Команды для клиента: (формат сообщений XX XX Serialized(this.MessageContent)) 5 | //Расшифровка XX XX: 6 | //F 00 00: Регистрация принята 7 | //F 00 01: Регистрация не принята (ник уже существует) 8 | 9 | //F 00 10: Вывести общее сообщение для комнаты 10 | //F 00 11: Вывести личное сообщение 11 | //F 00 13: Вывести системное сообщение 12 | //F 00 14: Remove messages 13 | 14 | //F 00 30: Открыта комната 15 | //F 00 31: Закрыта комната 16 | //F 00 32: Комната обновлена 17 | 18 | //F 00 40: Опубликовать файл 19 | //F 00 41: Файл больше не раздается 20 | //F 00 42: Прочитать часть файла 21 | //F 00 43: Записать часть файла 22 | 23 | //F 00 50: Ожидать прямое соединение 24 | //F 00 51: Выполнить прямое соединение 25 | //F 00 52: Подключится к сервису P2P 26 | 27 | //F 00 60: Воспроизвести голос 28 | 29 | //F 00 FF: Пинг ответ 30 | 31 | //F FF FF: Пустая команда 32 | 33 | enum ClientCommandId : long 34 | { 35 | RegistrationResponse = 0xF0000, 36 | 37 | OutRoomMessage = 0xF0010, 38 | OutPrivateMessage = 0xF0011, 39 | OutSystemMessage = 0xF0013, 40 | RemoveMessages = 0xF0014, 41 | 42 | RoomOpened = 0xF0030, 43 | RoomClosed = 0xF0031, 44 | RoomRefreshed = 0xF0032, 45 | 46 | FilePosted = 0xF0040, 47 | FileRemoved = 0xF0041, 48 | ReadFilePart = 0xF0042, 49 | WriteFilePart = 0xF0043, 50 | 51 | WaitPeerConnection = 0xF0050, 52 | ConnectToPeer = 0xF0051, 53 | ConnectToP2PService = 0xF0052, 54 | 55 | PlayVoice = 0xF0060, 56 | 57 | PingResponce = 0xF00FF, 58 | 59 | Empty = 0xFFFFF 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Engine/Api/Client/Files/ClientAddFileAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Files; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.IO; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Client.Files 8 | { 9 | [Serializable] 10 | public class ClientAddFileAction : IAction 11 | { 12 | private readonly string _roomName; 13 | private readonly string _fileName; 14 | 15 | /// 16 | /// Add file to room. 17 | /// 18 | /// Room name. 19 | /// Full path to file. 20 | [SecuritySafeCritical] 21 | public ClientAddFileAction(string roomName, string fileName) 22 | { 23 | if (string.IsNullOrEmpty(roomName)) 24 | throw new ArgumentException("roomName"); 25 | 26 | if (string.IsNullOrEmpty(fileName)) 27 | throw new ArgumentException("fileName"); 28 | 29 | _roomName = roomName; 30 | _fileName = fileName; 31 | } 32 | 33 | [SecuritySafeCritical] 34 | public void Perform() 35 | { 36 | var info = new FileInfo(_fileName); 37 | if (!info.Exists) 38 | throw new InvalidOperationException("File not exist."); 39 | 40 | using (var client = ClientModel.Get()) 41 | { 42 | var posted = client.Chat.GetOrCreatePostedFile(info, _roomName); 43 | var sendingContent = new ServerAddFileToRoomCommand.MessageContent { RoomName = _roomName, File = posted.File.ToDto() }; 44 | ClientModel.Client.SendMessage(ServerAddFileToRoomCommand.CommandId, sendingContent); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Engine/Api/Client/Files/ClientDownloadFileAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Exceptions; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Entities; 4 | using Engine.Network; 5 | using System; 6 | using System.Security; 7 | 8 | namespace Engine.Api.Client.Files 9 | { 10 | [Serializable] 11 | public class ClientDownloadFileAction : IAction 12 | { 13 | private readonly string _roomName; 14 | private readonly FileId _fileId; 15 | private readonly string _savePath; 16 | 17 | /// 18 | /// Download file. 19 | /// 20 | /// Room name where file was posted. 21 | /// File identifier. 22 | /// Path for file saving. 23 | [SecuritySafeCritical] 24 | public ClientDownloadFileAction(string roomName, FileId fileId, string savePath) 25 | { 26 | if (string.IsNullOrEmpty(roomName)) 27 | throw new ArgumentException("roomName"); 28 | 29 | if (string.IsNullOrEmpty(savePath)) 30 | throw new ArgumentException("savePath"); 31 | 32 | _roomName = roomName; 33 | _fileId = fileId; 34 | _savePath = savePath; 35 | } 36 | 37 | [SecuritySafeCritical] 38 | public void Perform() 39 | { 40 | using (var client = ClientModel.Get()) 41 | { 42 | var chat = client.Chat; 43 | var room = chat.GetRoom(_roomName); 44 | 45 | if (chat.IsFileDownloading(_fileId)) 46 | throw new ModelException(ErrorCode.FileAlreadyDownloading, _fileId); 47 | 48 | var file = room.TryGetFile(_fileId); 49 | if (file == null) 50 | throw new ModelException(ErrorCode.FileInRoomNotFound); 51 | 52 | if (chat.User.Equals(file.Id.Owner)) 53 | throw new ModelException(ErrorCode.CantDownloadOwnFile); 54 | 55 | chat.AddFileDownload(new DownloadingFile(file, _savePath)); 56 | 57 | var sendingContent = new ClientReadFilePartCommand.MessageContent 58 | { 59 | File = file.ToDto(), 60 | Length = AsyncClient.DefaultFilePartSize, 61 | RoomName = _roomName, 62 | StartPartPosition = 0, 63 | }; 64 | 65 | ClientModel.Peer.SendMessage(file.Id.Owner, ClientReadFilePartCommand.CommandId, sendingContent); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Engine/Api/Client/Files/ClientFilePostedCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using Engine.Model.Common.Dto; 5 | using Engine.Model.Common.Entities; 6 | using ThirtyNineEighty.BinarySerializer; 7 | 8 | namespace Engine.Api.Client.Files 9 | { 10 | [SecurityCritical] 11 | class ClientFilePostedCommand : 12 | ClientCommand 13 | { 14 | public const long CommandId = (long)ClientCommandId.FilePosted; 15 | 16 | public override long Id 17 | { 18 | [SecuritySafeCritical] 19 | get { return CommandId; } 20 | } 21 | 22 | [SecuritySafeCritical] 23 | protected override void OnRun(MessageContent content, CommandArgs args) 24 | { 25 | if (content.File == null) 26 | throw new ArgumentNullException(nameof(content.File)); 27 | 28 | if (string.IsNullOrEmpty(content.RoomName)) 29 | throw new ArgumentException(nameof(content.RoomName)); 30 | 31 | using (var client = ClientModel.Get()) 32 | { 33 | var room = client.Chat.GetRoom(content.RoomName); 34 | 35 | // File may be posted twice, it's allowed 36 | if (!room.IsFileExist(content.File.Id)) 37 | room.AddFile(new FileDescription(content.File)); 38 | } 39 | 40 | var receiveMessageArgs = new ReceiveMessageEventArgs 41 | { 42 | Type = MessageType.File, 43 | MessageId = Room.SpecificMessageId, 44 | Time = DateTime.UtcNow, 45 | Message = content.File.Name, 46 | Sender = content.File.Id.Owner, 47 | RoomName = content.RoomName, 48 | FileId = content.File.Id, 49 | }; 50 | 51 | ClientModel.Notifier.ReceiveMessage(receiveMessageArgs); 52 | } 53 | 54 | [Serializable] 55 | [BinType("ClientFilePosted")] 56 | public class MessageContent 57 | { 58 | [BinField("f")] 59 | public FileDescriptionDto File; 60 | 61 | [BinField("r")] 62 | public string RoomName; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Engine/Api/Client/Files/ClientFileRemovedCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using Engine.Model.Common.Entities; 5 | using ThirtyNineEighty.BinarySerializer; 6 | 7 | namespace Engine.Api.Client.Files 8 | { 9 | [SecurityCritical] 10 | class ClientFileRemovedCommand : 11 | ClientCommand 12 | { 13 | public const long CommandId = (long)ClientCommandId.FileRemoved; 14 | 15 | public override long Id 16 | { 17 | [SecuritySafeCritical] 18 | get { return CommandId; } 19 | } 20 | 21 | [SecuritySafeCritical] 22 | protected override void OnRun(MessageContent content, CommandArgs args) 23 | { 24 | if (string.IsNullOrEmpty(content.RoomName)) 25 | throw new ArgumentException("content.RoomName"); 26 | 27 | using (var client = ClientModel.Get()) 28 | { 29 | // Remove file from room 30 | var room = client.Chat.TryGetRoom(content.RoomName); 31 | if (room != null) 32 | room.RemoveFile(content.FileId); 33 | } 34 | } 35 | 36 | [Serializable] 37 | [BinType("ClientFileRemoved")] 38 | public class MessageContent 39 | { 40 | [BinField("r")] 41 | public string RoomName; 42 | 43 | [BinField("f")] 44 | public FileId FileId; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Engine/Api/Client/Files/ClientRemoveFileAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Files; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Entities; 4 | using System; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Client.Files 8 | { 9 | [Serializable] 10 | public class ClientRemoveFileAction : IAction 11 | { 12 | private readonly string _roomName; 13 | private readonly FileId _fileId; 14 | 15 | /// 16 | /// Remove posted file from room. 17 | /// 18 | /// Room name that contain removing file. 19 | /// File identifier. 20 | [SecuritySafeCritical] 21 | public ClientRemoveFileAction(string roomName, FileId fileId) 22 | { 23 | if (string.IsNullOrEmpty(roomName)) 24 | throw new ArgumentException("roomName"); 25 | 26 | _roomName = roomName; 27 | _fileId = fileId; 28 | } 29 | 30 | [SecuritySafeCritical] 31 | public void Perform() 32 | { 33 | using (var client = ClientModel.Get()) 34 | client.Chat.RemovePostedFile(_roomName, _fileId); 35 | 36 | var sendingContent = new ServerRemoveFileFromRoomCommand.MessageContent { RoomName = _roomName, FileId = _fileId }; 37 | ClientModel.Client.SendMessage(ServerRemoveFileFromRoomCommand.CommandId, sendingContent); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Engine/Api/Client/Messages/ClientOutPrivateMessageCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using ThirtyNineEighty.BinarySerializer; 5 | 6 | namespace Engine.Api.Client.Messages 7 | { 8 | [SecurityCritical] 9 | class ClientOutPrivateMessageCommand 10 | : ClientCommand 11 | { 12 | public const long CommandId = (long)ClientCommandId.OutPrivateMessage; 13 | 14 | public override long Id 15 | { 16 | [SecuritySafeCritical] 17 | get { return CommandId; } 18 | } 19 | 20 | protected override bool IsPeerCommand 21 | { 22 | [SecuritySafeCritical] 23 | get { return true; } 24 | } 25 | 26 | [SecuritySafeCritical] 27 | protected override void OnRun(MessageContent content, CommandArgs args) 28 | { 29 | if (content.Text == null) 30 | throw new ArgumentNullException(nameof(content.Text)); 31 | 32 | var receiveMessageArgs = new ReceiveMessageEventArgs 33 | { 34 | Type = MessageType.Private, 35 | Time = DateTime.UtcNow, 36 | Message = content.Text, 37 | Sender = args.ConnectionId, 38 | }; 39 | 40 | ClientModel.Notifier.ReceiveMessage(receiveMessageArgs); 41 | } 42 | 43 | [Serializable] 44 | [BinType("ClientOutPrivateMessage")] 45 | public class MessageContent 46 | { 47 | [BinField("t")] 48 | public string Text; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Engine/Api/Client/Messages/ClientOutRoomMessageCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using Engine.Model.Common.Dto; 5 | using Engine.Model.Common.Entities; 6 | using ThirtyNineEighty.BinarySerializer; 7 | 8 | namespace Engine.Api.Client.Messages 9 | { 10 | [SecurityCritical] 11 | class ClientOutRoomMessageCommand : 12 | ClientCommand 13 | { 14 | public const long CommandId = (long)ClientCommandId.OutRoomMessage; 15 | 16 | public override long Id 17 | { 18 | [SecuritySafeCritical] 19 | get { return CommandId; } 20 | } 21 | 22 | [SecuritySafeCritical] 23 | protected override void OnRun(MessageContent content, CommandArgs args) 24 | { 25 | if (content.Message == null) 26 | throw new ArgumentException("content.Message"); 27 | 28 | if (string.IsNullOrEmpty(content.RoomName)) 29 | throw new ArgumentException("ontent.RoomName"); 30 | 31 | using (var client = ClientModel.Get()) 32 | { 33 | var room = client.Chat.GetRoom(content.RoomName); 34 | room.AddMessage(new Message(content.Message)); 35 | 36 | var receiveMessageArgs = new ReceiveMessageEventArgs 37 | { 38 | Type = MessageType.Common, 39 | RoomName = content.RoomName, 40 | MessageId = content.Message.Id, 41 | Time = content.Message.Time, 42 | Message = content.Message.Text, 43 | Sender = content.Message.Owner, 44 | }; 45 | 46 | ClientModel.Notifier.ReceiveMessage(receiveMessageArgs); 47 | } 48 | } 49 | 50 | [Serializable] 51 | [BinType("ClientOutRoomMessage")] 52 | public class MessageContent 53 | { 54 | [BinField("m")] 55 | public MessageDto Message; 56 | 57 | [BinField("r")] 58 | public string RoomName; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Engine/Api/Client/Messages/ClientOutSystemMessageCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using Engine.Model.Common.Entities; 5 | using ThirtyNineEighty.BinarySerializer; 6 | 7 | namespace Engine.Api.Client.Messages 8 | { 9 | [SecurityCritical] 10 | class ClientOutSystemMessageCommand : 11 | ClientCommand 12 | { 13 | public const long CommandId = (long)ClientCommandId.OutSystemMessage; 14 | 15 | public override long Id 16 | { 17 | [SecuritySafeCritical] 18 | get { return CommandId; } 19 | } 20 | 21 | [SecuritySafeCritical] 22 | protected override void OnRun(MessageContent content, CommandArgs args) 23 | { 24 | if (content.Message == SystemMessageId.None) 25 | throw new ArgumentException("content.Message"); 26 | 27 | ClientModel.Notifier.ReceiveMessage(new ReceiveMessageEventArgs 28 | { 29 | SystemMessage = content.Message, 30 | SystemMessageFormat = content.FormatParams, 31 | Time = DateTime.UtcNow, 32 | Type = MessageType.System 33 | }); 34 | } 35 | 36 | [Serializable] 37 | [BinType("ClientOutSystemMessage")] 38 | public class MessageContent 39 | { 40 | [BinField("m")] 41 | public SystemMessageId Message; 42 | 43 | [BinField("p")] 44 | public string[] FormatParams; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Engine/Api/Client/Messages/ClientRemoveMessagesCommand.cs: -------------------------------------------------------------------------------- 1 | using Engine.Exceptions; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Security; 6 | using ThirtyNineEighty.BinarySerializer; 7 | 8 | namespace Engine.Api.Client.Messages 9 | { 10 | public class ClientRemoveMessagesCommand : 11 | ClientCommand 12 | { 13 | public const long CommandId = (long)ClientCommandId.RemoveMessages; 14 | 15 | public override long Id 16 | { 17 | [SecuritySafeCritical] 18 | get { return CommandId; } 19 | } 20 | 21 | [SecuritySafeCritical] 22 | protected override void OnRun(MessageContent content, CommandArgs args) 23 | { 24 | if (string.IsNullOrEmpty(content.RoomName)) 25 | throw new ArgumentException("room name is null or empty"); 26 | 27 | using (var client = ClientModel.Get()) 28 | { 29 | var room = client.Chat.TryGetRoom(content.RoomName); 30 | if (room == null) 31 | throw new ModelException(ErrorCode.RoomNotFound); 32 | 33 | room.RemoveMessages(content.Ids); 34 | } 35 | 36 | var removed = new HashSet(content.Ids); 37 | ClientModel.Notifier.RoomRefreshed(new RoomRefreshedEventArgs(content.RoomName, null, removed)); 38 | } 39 | 40 | [Serializable] 41 | [BinType("ClientRemoveMessages")] 42 | public class MessageContent 43 | { 44 | [BinField("r")] 45 | public string RoomName; 46 | 47 | [BinField("i")] 48 | public long[] Ids; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Engine/Api/Client/Messages/ClientSendMessageAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Messages; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api.Client.Messages 7 | { 8 | [Serializable] 9 | public class ClientSendMessageAction : IAction 10 | { 11 | private readonly string _roomName; 12 | private readonly long? _messageId; 13 | private readonly string _text; 14 | 15 | /// 16 | /// Send message. 17 | /// 18 | /// Room name. 19 | /// Message text. 20 | [SecuritySafeCritical] 21 | public ClientSendMessageAction(string roomName, string text) 22 | : this(roomName, null, text) 23 | { 24 | 25 | } 26 | 27 | /// 28 | /// Edit message. 29 | /// 30 | /// Room name. 31 | /// Message id which be edited. 32 | /// Message text. 33 | [SecuritySafeCritical] 34 | public ClientSendMessageAction(string roomName, long messageId, string text) 35 | : this(roomName, (long?)messageId, text) 36 | { 37 | 38 | } 39 | 40 | [SecuritySafeCritical] 41 | private ClientSendMessageAction(string roomName, long? messageId, string text) 42 | { 43 | if (string.IsNullOrEmpty(roomName)) 44 | throw new ArgumentException("roomName"); 45 | 46 | if (string.IsNullOrEmpty(text)) 47 | throw new ArgumentNullException("text"); 48 | 49 | _roomName = roomName; 50 | _messageId = messageId; 51 | _text = text; 52 | } 53 | 54 | [SecuritySafeCritical] 55 | public void Perform() 56 | { 57 | var sendingContent = new ServerSendRoomMessageCommand.MessageContent { RoomName = _roomName, MessageId = _messageId, Text = _text }; 58 | ClientModel.Client.SendMessage(ServerSendRoomMessageCommand.CommandId, sendingContent); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Engine/Api/Client/Messages/ClientSendPrivateMessageAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Client; 2 | using Engine.Model.Common.Entities; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api.Client.Messages 7 | { 8 | [Serializable] 9 | public class ClientSendPrivateMessageAction : IAction 10 | { 11 | private readonly UserId _reciverId; 12 | private readonly string _text; 13 | 14 | /// 15 | /// Send private message to user. 16 | /// 17 | /// Reciver id. 18 | /// Message text. 19 | [SecuritySafeCritical] 20 | public ClientSendPrivateMessageAction(UserId reciverId, string text) 21 | { 22 | if (reciverId == UserId.Empty) 23 | throw new ArgumentException(nameof(reciverId)); 24 | 25 | if (string.IsNullOrEmpty(text)) 26 | throw new ArgumentNullException(nameof(text)); 27 | 28 | _reciverId = reciverId; 29 | _text = text; 30 | } 31 | 32 | [SecuritySafeCritical] 33 | public void Perform() 34 | { 35 | var sendingContent = new ClientOutPrivateMessageCommand.MessageContent { Text = _text }; 36 | ClientModel.Peer.SendMessage(_reciverId, ClientOutPrivateMessageCommand.CommandId, sendingContent); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Engine/Api/Client/Others/ClientEmptyCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | 3 | namespace Engine.Api.Client.Others 4 | { 5 | [SecurityCritical] 6 | class ClientEmptyCommand : ClientCommand 7 | { 8 | public const long CommandId = (long)ClientCommandId.Empty; 9 | public static readonly ClientEmptyCommand Empty = new ClientEmptyCommand(); 10 | 11 | public override long Id 12 | { 13 | [SecuritySafeCritical] 14 | get { return CommandId; } 15 | } 16 | 17 | [SecuritySafeCritical] 18 | protected override void OnRun(CommandArgs args) 19 | { 20 | 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Engine/Api/Client/Others/ClientPingResponseCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | 3 | namespace Engine.Api.Client.Others 4 | { 5 | [SecurityCritical] 6 | class ClientPingResponseCommand : ClientCommand 7 | { 8 | public const long CommandId = (long)ClientCommandId.PingResponce; 9 | 10 | public override long Id 11 | { 12 | [SecuritySafeCritical] 13 | get { return CommandId; } 14 | } 15 | 16 | [SecuritySafeCritical] 17 | protected override void OnRun(CommandArgs args) 18 | { 19 | 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Engine/Api/Client/P2P/ClientConnectToP2PServiceCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Security; 4 | using Engine.Model.Client; 5 | using ThirtyNineEighty.BinarySerializer; 6 | 7 | namespace Engine.Api.Client.P2P 8 | { 9 | [SecurityCritical] 10 | class ClientConnectToP2PServiceCommand : 11 | ClientCommand 12 | { 13 | public const long CommandId = (long)ClientCommandId.ConnectToP2PService; 14 | 15 | public override long Id 16 | { 17 | [SecuritySafeCritical] 18 | get { return CommandId; } 19 | } 20 | 21 | [SecuritySafeCritical] 22 | protected override void OnRun(MessageContent content, CommandArgs args) 23 | { 24 | var address = ClientModel.Client.RemotePoint.Address; 25 | var endPoint = new IPEndPoint(address, content.Port); 26 | 27 | ClientModel.Peer.ConnectToService(endPoint); 28 | } 29 | 30 | [Serializable] 31 | [BinType("ClientConnectToP2PService")] 32 | public class MessageContent 33 | { 34 | [BinField("p")] 35 | public int Port; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Engine/Api/Client/P2P/ClientConnectToPeerAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.P2P; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Entities; 4 | using System; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Client.P2P 8 | { 9 | public class ClientConnectToPeerAction : IAction 10 | { 11 | private readonly UserId _userId; 12 | 13 | /// 14 | /// Initiate new direct connection to other user. 15 | /// If connection already exist then action do nothing. 16 | /// 17 | /// User nick. 18 | [SecuritySafeCritical] 19 | public ClientConnectToPeerAction(UserId userId) 20 | { 21 | if (userId == UserId.Empty) 22 | throw new ArgumentException(nameof(userId)); 23 | 24 | _userId = userId; 25 | } 26 | 27 | [SecuritySafeCritical] 28 | public void Perform() 29 | { 30 | if (ClientModel.Peer.IsConnected(_userId)) 31 | { 32 | ClientModel.Logger.WriteDebug("Client already connected to {0}", _userId); 33 | } 34 | else 35 | { 36 | var sendingContent = new ServerP2PConnectRequestCommand.MessageContent { UserId = _userId }; 37 | ClientModel.Client.SendMessage(ServerP2PConnectRequestCommand.CommandId, sendingContent); 38 | ClientModel.Logger.WriteDebug("Connecting directly to {0}...", _userId); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Engine/Api/Client/P2P/ClientConnectToPeerCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Security; 4 | using Engine.Model.Client; 5 | using Engine.Model.Common.Dto; 6 | using ThirtyNineEighty.BinarySerializer; 7 | 8 | namespace Engine.Api.Client.P2P 9 | { 10 | [SecurityCritical] 11 | class ClientConnectToPeerCommand : 12 | ClientCommand 13 | { 14 | public const long CommandId = (long)ClientCommandId.ConnectToPeer; 15 | 16 | public override long Id 17 | { 18 | [SecuritySafeCritical] 19 | get { return CommandId; } 20 | } 21 | 22 | [SecuritySafeCritical] 23 | protected override void OnRun(MessageContent content, CommandArgs args) 24 | { 25 | if (content.RemoteInfo == null) 26 | throw new ArgumentNullException("content.RemoteInfo"); 27 | 28 | var peerPoint = new IPEndPoint(new IPAddress(content.IPAddress), content.Port); 29 | ClientModel.Peer.ConnectToPeer(content.RemoteInfo.Id, peerPoint); 30 | ClientModel.Logger.WriteDebug("ClientConnectToPeerCommand: {0}|{1}", content.RemoteInfo.Id, peerPoint.ToString()); 31 | } 32 | 33 | [Serializable] 34 | [BinType("ClientConnectToPeer")] 35 | public class MessageContent 36 | { 37 | [BinField("p")] 38 | public int Port; 39 | 40 | [BinField("a")] 41 | public byte[] IPAddress; 42 | 43 | [BinField("u")] 44 | public UserDto RemoteInfo; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Engine/Api/Client/P2P/ClientWaitPeerConnectionCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Security; 4 | using Engine.Api.Server.P2P; 5 | using Engine.Model.Client; 6 | using Engine.Model.Common.Dto; 7 | using ThirtyNineEighty.BinarySerializer; 8 | 9 | namespace Engine.Api.Client.P2P 10 | { 11 | [SecurityCritical] 12 | class ClientWaitPeerConnectionCommand : 13 | ClientCommand 14 | { 15 | public const long CommandId = (long)ClientCommandId.WaitPeerConnection; 16 | 17 | public override long Id 18 | { 19 | [SecuritySafeCritical] 20 | get { return CommandId; } 21 | } 22 | 23 | [SecuritySafeCritical] 24 | protected override void OnRun(MessageContent content, CommandArgs args) 25 | { 26 | if (content.RemoteInfo == null) 27 | throw new ArgumentNullException("content.RemoteInfo"); 28 | 29 | var senderPoint = new IPEndPoint(new IPAddress(content.SenderIpAddress), content.SenderPort); 30 | ClientModel.Peer.WaitConnection(senderPoint); 31 | 32 | var sendingContent = new ServerP2PReadyAcceptCommand.MessageContent 33 | { 34 | PeerPort = content.RequestPort, 35 | PeerIPAddress = content.RequestIpAddress, 36 | ReceiverId = content.RemoteInfo.Id 37 | }; 38 | 39 | using (var client = ClientModel.Get()) 40 | sendingContent.RemoteInfo = new UserDto(client.Chat.User); 41 | 42 | ClientModel.Client.SendMessage(ServerP2PReadyAcceptCommand.CommandId, sendingContent); 43 | 44 | ClientModel.Logger.WriteDebug("ClientWaitPeerConnectionCommand: {0}|{1}|{2}|{3}" 45 | , new IPAddress(sendingContent.PeerIPAddress) 46 | , sendingContent.PeerPort 47 | , sendingContent.ReceiverId 48 | , sendingContent.RemoteInfo.Id 49 | ); 50 | } 51 | 52 | [Serializable] 53 | [BinType("ClientWaitPeerConnection")] 54 | public class MessageContent 55 | { 56 | [BinField("u")] 57 | public UserDto RemoteInfo; 58 | 59 | [BinField("sp")] 60 | public int SenderPort; 61 | 62 | [BinField("sa")] 63 | public byte[] SenderIpAddress; 64 | 65 | [BinField("rp")] 66 | public int RequestPort; 67 | 68 | [BinField("ra")] 69 | public byte[] RequestIpAddress; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Engine/Api/Client/Registrations/ClientRegisterAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Registrations; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Dto; 4 | using System; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Client.Registrations 8 | { 9 | [Serializable] 10 | public class ClientRegisterAction : IAction 11 | { 12 | /// 13 | /// Send registration request. 14 | /// 15 | [SecuritySafeCritical] 16 | public ClientRegisterAction() 17 | { 18 | } 19 | 20 | [SecuritySafeCritical] 21 | public void Perform() 22 | { 23 | using (var client = ClientModel.Get()) 24 | { 25 | var sendingContent = new ServerRegisterCommand.MessageContent { UserDto = new UserDto(client.Chat.User) }; 26 | ClientModel.Client.SendMessage(ServerRegisterCommand.CommandId, sendingContent); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Engine/Api/Client/Registrations/ClientRegistrationResponseCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using Engine.Model.Common.Entities; 5 | using ThirtyNineEighty.BinarySerializer; 6 | 7 | namespace Engine.Api.Client.Registrations 8 | { 9 | [SecurityCritical] 10 | class ClientRegistrationResponseCommand : 11 | ClientCommand 12 | { 13 | public const long CommandId = (long)ClientCommandId.RegistrationResponse; 14 | 15 | public override long Id 16 | { 17 | [SecuritySafeCritical] 18 | get { return CommandId; } 19 | } 20 | 21 | [SecuritySafeCritical] 22 | protected override void OnRun(MessageContent content, CommandArgs args) 23 | { 24 | var eventArgs = new RegistrationEventArgs(content.Registered, content.Message); 25 | ClientModel.Notifier.ReceiveRegistrationResponse(eventArgs); 26 | } 27 | 28 | [Serializable] 29 | [BinType("ClientRegistrationResponse")] 30 | public class MessageContent 31 | { 32 | [BinField("r")] 33 | public bool Registered; 34 | 35 | [BinField("m")] 36 | public SystemMessageId Message; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Engine/Api/Client/Registrations/ClientUnregistrerAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Registrations; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api.Client.Registrations 7 | { 8 | [Serializable] 9 | public class ClientUnregisterAction : IAction 10 | { 11 | /// 12 | /// Send unregistration request. 13 | /// 14 | [SecuritySafeCritical] 15 | public ClientUnregisterAction() 16 | { 17 | } 18 | 19 | [SecuritySafeCritical] 20 | public void Perform() 21 | { 22 | ClientModel.Client.SendMessage(ServerUnregisterCommand.CommandId); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientCreateRoomAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Rooms; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Entities; 4 | using System; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Client.Rooms 8 | { 9 | [Serializable] 10 | public class ClientCreateRoomAction : IAction 11 | { 12 | private readonly string _roomName; 13 | private readonly RoomType _type; 14 | 15 | /// 16 | /// Creates room on server. 17 | /// 18 | /// Room name. 19 | /// Room type. 20 | [SecuritySafeCritical] 21 | public ClientCreateRoomAction(string roomName, RoomType type) 22 | { 23 | if (string.IsNullOrEmpty(roomName)) 24 | throw new ArgumentException("roomName"); 25 | 26 | if (type == RoomType.Unknown) 27 | throw new ArgumentException("type"); 28 | 29 | _roomName = roomName; 30 | _type = type; 31 | } 32 | 33 | [SecuritySafeCritical] 34 | public void Perform() 35 | { 36 | var sendingContent = new ServerCreateRoomCommand.MessageContent { RoomName = _roomName, Type = _type }; 37 | ClientModel.Client.SendMessage(ServerCreateRoomCommand.CommandId, sendingContent); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientDeleteRoomAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Rooms; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api.Client.Rooms 7 | { 8 | [Serializable] 9 | public class ClientDeleteRoomAction : IAction 10 | { 11 | private readonly string _roomName; 12 | 13 | /// 14 | /// Remove room on server. 15 | /// 16 | /// Removing room name. 17 | [SecuritySafeCritical] 18 | public ClientDeleteRoomAction(string roomName) 19 | { 20 | if (string.IsNullOrEmpty(roomName)) 21 | throw new ArgumentException("roomName"); 22 | 23 | _roomName = roomName; 24 | } 25 | 26 | [SecuritySafeCritical] 27 | public void Perform() 28 | { 29 | var sendingContent = new ServerDeleteRoomCommand.MessageContent { RoomName = _roomName }; 30 | ClientModel.Client.SendMessage(ServerDeleteRoomCommand.CommandId, sendingContent); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientExitFromRoomAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Rooms; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api.Client.Rooms 7 | { 8 | [Serializable] 9 | public class ClientExitFromRoomAction : IAction 10 | { 11 | private readonly string _roomName; 12 | 13 | /// 14 | /// Exit from room. 15 | /// 16 | /// Room name. 17 | [SecuritySafeCritical] 18 | public ClientExitFromRoomAction(string roomName) 19 | { 20 | if (string.IsNullOrEmpty(roomName)) 21 | throw new ArgumentException("roomName"); 22 | 23 | _roomName = roomName; 24 | } 25 | 26 | [SecuritySafeCritical] 27 | public void Perform() 28 | { 29 | var sendingContent = new ServerExitFromRoomCommand.MessageContent { RoomName = _roomName }; 30 | ClientModel.Client.SendMessage(ServerExitFromRoomCommand.CommandId, sendingContent); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientInviteUsersAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Rooms; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Security; 8 | 9 | namespace Engine.Api.Client.Rooms 10 | { 11 | [Serializable] 12 | public class ClientInviteUsersAction : IAction 13 | { 14 | private readonly string _roomName; 15 | private readonly UserId[] _users; 16 | 17 | /// 18 | /// Invites users to room. 19 | /// 20 | /// Room name. 21 | /// Users to be invited. 22 | [SecuritySafeCritical] 23 | public ClientInviteUsersAction(string roomName, IEnumerable users) 24 | { 25 | if (string.IsNullOrEmpty(roomName)) 26 | throw new ArgumentException("roomName"); 27 | 28 | if (users == null) 29 | throw new ArgumentNullException("users"); 30 | 31 | _roomName = roomName; 32 | _users = users as UserId[] ?? users.ToArray(); 33 | } 34 | 35 | [SecuritySafeCritical] 36 | public void Perform() 37 | { 38 | var sendingContent = new ServerInviteUsersCommand.MessageContent { RoomName = _roomName, Users = _users }; 39 | ClientModel.Client.SendMessage(ServerInviteUsersCommand.CommandId, sendingContent); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientKickUsersAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Rooms; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Security; 8 | 9 | namespace Engine.Api.Client.Rooms 10 | { 11 | [Serializable] 12 | public class ClientKickUsersAction : IAction 13 | { 14 | private readonly string _roomName; 15 | private readonly UserId[] _users; 16 | 17 | /// 18 | /// Remove users from room. 19 | /// 20 | /// Room name. 21 | /// Users to be removed. 22 | [SecuritySafeCritical] 23 | public ClientKickUsersAction(string roomName, IEnumerable users) 24 | { 25 | if (string.IsNullOrEmpty(roomName)) 26 | throw new ArgumentException("roomName"); 27 | 28 | if (users == null) 29 | throw new ArgumentNullException("users"); 30 | 31 | _roomName = roomName; 32 | _users = users as UserId[] ?? users.ToArray(); 33 | } 34 | 35 | [SecuritySafeCritical] 36 | public void Perform() 37 | { 38 | var sendingContent = new ServerKickUsersCommand.MessageContent { RoomName = _roomName, Users = _users }; 39 | ClientModel.Client.SendMessage(ServerKickUsersCommand.CommandId, sendingContent); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientRefreshRoomAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Rooms; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api.Client.Rooms 7 | { 8 | [Serializable] 9 | public class ClientRefreshRoomAction : IAction 10 | { 11 | private readonly string _roomName; 12 | 13 | /// 14 | /// Send refresh room request on server. 15 | /// 16 | /// Room name. 17 | [SecuritySafeCritical] 18 | public ClientRefreshRoomAction(string roomName) 19 | { 20 | if (string.IsNullOrEmpty(roomName)) 21 | throw new ArgumentException("roomName"); 22 | 23 | _roomName = roomName; 24 | } 25 | 26 | [SecuritySafeCritical] 27 | public void Perform() 28 | { 29 | var sendingContent = new ServerRefreshRoomCommand.MessageContent { RoomName = _roomName }; 30 | ClientModel.Client.SendMessage(ServerRefreshRoomCommand.CommandId, sendingContent); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientRoomClosedCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using ThirtyNineEighty.BinarySerializer; 5 | 6 | namespace Engine.Api.Client.Rooms 7 | { 8 | [SecurityCritical] 9 | class ClientRoomClosedCommand : 10 | ClientCommand 11 | { 12 | public const long CommandId = (long)ClientCommandId.RoomClosed; 13 | 14 | public override long Id 15 | { 16 | [SecuritySafeCritical] 17 | get { return CommandId; } 18 | } 19 | 20 | [SecuritySafeCritical] 21 | protected override void OnRun(MessageContent content, CommandArgs args) 22 | { 23 | if (content.RoomName == null) 24 | throw new ArgumentNullException("content.RoomName"); 25 | 26 | using (var client = ClientModel.Get()) 27 | client.Chat.RemoveRoom(content.RoomName); 28 | 29 | ClientModel.Notifier.RoomClosed(new RoomClosedEventArgs(content.RoomName)); 30 | } 31 | 32 | [Serializable] 33 | [BinType("ClientRoomClosed")] 34 | public class MessageContent 35 | { 36 | [BinField("r")] 37 | public string RoomName; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientRoomOpenedCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Client.P2P; 4 | using Engine.Exceptions; 5 | using Engine.Model.Client; 6 | using Engine.Model.Client.Entities; 7 | using Engine.Model.Common.Dto; 8 | using Engine.Model.Common.Entities; 9 | using ThirtyNineEighty.BinarySerializer; 10 | 11 | namespace Engine.Api.Client.Rooms 12 | { 13 | [SecurityCritical] 14 | class ClientRoomOpenedCommand : 15 | ClientCommand 16 | { 17 | public const long CommandId = (long)ClientCommandId.RoomOpened; 18 | 19 | public override long Id 20 | { 21 | [SecuritySafeCritical] 22 | get { return CommandId; } 23 | } 24 | 25 | [SecuritySafeCritical] 26 | protected override void OnRun(MessageContent content, CommandArgs args) 27 | { 28 | if (content.Room == null) 29 | throw new ArgumentNullException("content.Room"); 30 | 31 | using (var client = ClientModel.Get()) 32 | { 33 | Room room = null; 34 | if (content.Room.Type == RoomType.Chat) 35 | { 36 | var textRoom = new ClientRoom(content.Room); 37 | client.Chat.AddRoom(textRoom); 38 | room = textRoom; 39 | } 40 | 41 | if (content.Room.Type == RoomType.Voice) 42 | { 43 | var voiceRoom = new ClientVoiceRoom(content.Room); 44 | client.Chat.AddVoiceRoom(voiceRoom); 45 | room = voiceRoom; 46 | } 47 | 48 | if (room == null) 49 | throw new ModelException(ErrorCode.UnknownRoomType); 50 | 51 | AddUsers(client.Chat, content.Users); 52 | 53 | // Create P2P connections to users if need 54 | if (content.Room.ConnectTo != null) 55 | { 56 | foreach (var nick in content.Room.ConnectTo) 57 | ClientModel.Api.Perform(new ClientConnectToPeerAction(nick)); 58 | } 59 | 60 | room.Enable(); 61 | } 62 | 63 | ClientModel.Notifier.RoomOpened(new RoomOpenedEventArgs(content.Room.Name)); 64 | } 65 | 66 | [Serializable] 67 | [BinType("ClientRoomOpened")] 68 | public class MessageContent 69 | { 70 | [BinField("r")] 71 | public RoomDto Room; 72 | 73 | [BinField("u")] 74 | public UserDto[] Users; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Engine/Api/Client/Rooms/ClientSetRoomAdminAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Server.Rooms; 2 | using Engine.Model.Client; 3 | using Engine.Model.Common.Entities; 4 | using System; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Client.Rooms 8 | { 9 | [Serializable] 10 | public class ClientSetRoomAdminAction : IAction 11 | { 12 | private readonly string _roomName; 13 | private readonly UserId _newAdmin; 14 | 15 | /// 16 | /// Change room admin. 17 | /// 18 | /// Room name. 19 | /// New room admin. 20 | [SecuritySafeCritical] 21 | public ClientSetRoomAdminAction(string roomName, UserId newAdmin) 22 | { 23 | if (string.IsNullOrEmpty(roomName)) 24 | throw new ArgumentException(nameof(roomName)); 25 | 26 | if (newAdmin == UserId.Empty) 27 | throw new ArgumentException(nameof(newAdmin)); 28 | 29 | _roomName = roomName; 30 | _newAdmin = newAdmin; 31 | } 32 | 33 | [SecuritySafeCritical] 34 | public void Perform() 35 | { 36 | var sendingContent = new ServerSetRoomAdminCommand.MessageContent { RoomName = _roomName, NewAdmin = _newAdmin }; 37 | ClientModel.Client.SendMessage(ServerSetRoomAdminCommand.CommandId, sendingContent); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Engine/Api/Client/Voice/ClientPlayVoiceCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Model.Client; 4 | using Engine.Model.Common.Entities; 5 | using ThirtyNineEighty.BinarySerializer; 6 | 7 | namespace Engine.Api.Client.Voice 8 | { 9 | [SecurityCritical] 10 | class ClientPlayVoiceCommand : 11 | ClientCommand 12 | { 13 | public static long CommandId = (long)ClientCommandId.PlayVoice; 14 | 15 | public override long Id 16 | { 17 | [SecuritySafeCritical] 18 | get { return CommandId; } 19 | } 20 | 21 | protected override bool IsPeerCommand 22 | { 23 | [SecuritySafeCritical] 24 | get { return true; } 25 | } 26 | 27 | [SecuritySafeCritical] 28 | protected override void OnRun(MessageContent content, CommandArgs args) 29 | { 30 | using (var client = ClientModel.Get()) 31 | { 32 | var user = client.Chat.GetUser(args.ConnectionId); 33 | if (user.IsVoiceActive()) 34 | ClientModel.Player.Enqueue(args.ConnectionId, content.Number, content.Pack); 35 | } 36 | } 37 | 38 | [Serializable] 39 | [BinType("ClientPlayVoice")] 40 | public class MessageContent 41 | { 42 | [BinField("p")] 43 | public SoundPack Pack; 44 | 45 | [BinField("n")] 46 | public long Number; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Engine/Api/IAction.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Api 2 | { 3 | public interface IAction 4 | { 5 | void Perform(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Engine/Api/IApi.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine.Api 4 | { 5 | public interface IApi : IDisposable 6 | { 7 | /// 8 | /// Name and version of Api. 9 | /// 10 | string Name { get; } 11 | 12 | /// 13 | /// Get the command by identifier. 14 | /// 15 | /// Command identifier. 16 | /// Command. 17 | ICommand GetCommand(long id); 18 | 19 | /// 20 | /// Perform the remote action. 21 | /// 22 | /// Action to perform. 23 | void Perform(IAction action); 24 | } 25 | 26 | public static class Api 27 | { 28 | /// 29 | /// Name and version of Api. 30 | /// 31 | public const string Name = "StandardAPI v5.1"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Engine/Api/ICommand.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using Engine.Network; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Api 7 | { 8 | public interface ICommand 9 | { 10 | long Id { get; } 11 | void Run(CommandArgs args); 12 | } 13 | 14 | [Serializable] 15 | public sealed class CommandArgs : IDisposable 16 | { 17 | public UserId ConnectionId { get; private set; } 18 | public Unpacked Unpacked { get; private set; } 19 | 20 | public CommandArgs(UserId connectionId, Unpacked unpacked) 21 | { 22 | ConnectionId = connectionId; 23 | Unpacked = unpacked; 24 | } 25 | 26 | [SecuritySafeCritical] 27 | public void Dispose() 28 | { 29 | Unpacked.Dispose(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Engine/Api/Server/Files/ServerAddFileToRoomCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Client.Files; 4 | using Engine.Api.Server.Messages; 5 | using Engine.Model.Common.Dto; 6 | using Engine.Model.Common.Entities; 7 | using Engine.Model.Server; 8 | using ThirtyNineEighty.BinarySerializer; 9 | 10 | namespace Engine.Api.Server.Files 11 | { 12 | [SecurityCritical] 13 | class ServerAddFileToRoomCommand : 14 | ServerCommand 15 | { 16 | public const long CommandId = (long)ServerCommandId.AddFileToRoom; 17 | 18 | public override long Id 19 | { 20 | [SecuritySafeCritical] 21 | get { return CommandId; } 22 | } 23 | 24 | [SecuritySafeCritical] 25 | protected override void OnRun(MessageContent content, CommandArgs args) 26 | { 27 | if (string.IsNullOrEmpty(content.RoomName)) 28 | throw new ArgumentException(nameof(content.RoomName)); 29 | 30 | if (content.File == null) 31 | throw new ArgumentNullException(nameof(content.File)); 32 | 33 | using (var server = ServerModel.Get()) 34 | { 35 | Room room; 36 | if (!TryGetRoom(server.Chat, content.RoomName, args.ConnectionId, out room)) 37 | return; 38 | 39 | if (!room.IsUserExist(args.ConnectionId)) 40 | { 41 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomAccessDenied)); 42 | return; 43 | } 44 | 45 | if (!room.IsFileExist(content.File.Id)) 46 | room.AddFile(new FileDescription(content.File)); 47 | 48 | var sendingContent = new ClientFilePostedCommand.MessageContent 49 | { 50 | File = content.File, 51 | RoomName = content.RoomName 52 | }; 53 | 54 | foreach (var user in room.Users) 55 | ServerModel.Server.SendMessage(user, ClientFilePostedCommand.CommandId, sendingContent); 56 | } 57 | } 58 | 59 | [Serializable] 60 | [BinType("ServerAddFileToRoom")] 61 | public class MessageContent 62 | { 63 | [BinField("r")] 64 | public string RoomName; 65 | 66 | [BinField("f")] 67 | public FileDescriptionDto File; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Engine/Api/Server/Messages/ServerRemoveMessagesAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Client.Messages; 2 | using Engine.Model.Common.Entities; 3 | using Engine.Model.Server; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Security; 7 | 8 | namespace Engine.Api.Server.Messages 9 | { 10 | [SecuritySafeCritical] 11 | public class ServerRemoveMessagesAction : IAction 12 | { 13 | private readonly UserId _userId; 14 | private readonly string _roomName; 15 | private readonly long[] _ids; 16 | 17 | [SecuritySafeCritical] 18 | public ServerRemoveMessagesAction(UserId userId, string roomName, IEnumerable ids) 19 | { 20 | _userId = userId; 21 | _roomName = roomName; 22 | _ids = ids as long[] ?? ids.ToArray(); 23 | } 24 | 25 | [SecuritySafeCritical] 26 | public void Perform() 27 | { 28 | var messageContent = new ClientRemoveMessagesCommand.MessageContent { RoomName = _roomName, Ids = _ids }; 29 | ServerModel.Server.SendMessage(_userId, ClientRemoveMessagesCommand.CommandId, messageContent); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Engine/Api/Server/Messages/ServerSendSystemMessageAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Client.Messages; 2 | using Engine.Model.Common.Entities; 3 | using Engine.Model.Server; 4 | using System; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Server.Messages 8 | { 9 | [Serializable] 10 | public class ServerSendSystemMessageAction : IAction 11 | { 12 | private readonly UserId _userId; 13 | private readonly SystemMessageId _message; 14 | private readonly string[] _formatParams; 15 | 16 | /// 17 | /// Send system message to user. 18 | /// 19 | /// Reciver of system message. 20 | /// System message id. 21 | /// Format params for message. 22 | [SecuritySafeCritical] 23 | public ServerSendSystemMessageAction(UserId userId, SystemMessageId message, params string[] formatParams) 24 | { 25 | _userId = userId; 26 | _message = message; 27 | _formatParams = formatParams; 28 | } 29 | 30 | [SecuritySafeCritical] 31 | public void Perform() 32 | { 33 | var sendingContent = new ClientOutSystemMessageCommand.MessageContent { Message = _message, FormatParams = _formatParams }; 34 | ServerModel.Server.SendMessage(_userId, ClientOutSystemMessageCommand.CommandId, sendingContent); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Engine/Api/Server/Others/ServerEmptyCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | 3 | namespace Engine.Api.Server.Others 4 | { 5 | [SecurityCritical] 6 | class ServerEmptyCommand : ServerCommand 7 | { 8 | public const long CommandId = (long)ServerCommandId.Empty; 9 | public static readonly ServerEmptyCommand Empty = new ServerEmptyCommand(); 10 | 11 | public override long Id 12 | { 13 | [SecuritySafeCritical] 14 | get { return CommandId; } 15 | } 16 | 17 | [SecurityCritical] 18 | protected ServerEmptyCommand() 19 | { 20 | 21 | } 22 | 23 | [SecuritySafeCritical] 24 | protected override void OnRun(CommandArgs args) 25 | { 26 | 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Engine/Api/Server/Others/ServerPingRequestCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | using Engine.Api.Client.Others; 3 | using Engine.Model.Server; 4 | 5 | namespace Engine.Api.Server.Others 6 | { 7 | [SecurityCritical] 8 | class ServerPingRequestCommand : ServerCommand 9 | { 10 | public const long CommandId = (long)ServerCommandId.PingRequest; 11 | 12 | public override long Id 13 | { 14 | [SecuritySafeCritical] 15 | get { return CommandId; } 16 | } 17 | 18 | [SecuritySafeCritical] 19 | protected override void OnRun(CommandArgs args) 20 | { 21 | ServerModel.Server.SendMessage(args.ConnectionId, ClientPingResponseCommand.CommandId, true); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Engine/Api/Server/P2P/ServerIntroduceConnectionsAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Client.P2P; 2 | using Engine.Model.Common.Dto; 3 | using Engine.Model.Common.Entities; 4 | using Engine.Model.Server; 5 | using System; 6 | using System.Net; 7 | using System.Security; 8 | 9 | namespace Engine.Api.Server.P2P 10 | { 11 | [Serializable] 12 | public class ServerIntroduceConnectionsAction : IAction 13 | { 14 | private readonly UserId _senderId; 15 | private readonly IPEndPoint _senderPoint; 16 | private readonly UserId _requestId; 17 | private readonly IPEndPoint _requestPoint; 18 | 19 | /// 20 | /// Connect users directly. 21 | /// 22 | /// User who request direct connection. 23 | /// Address of user who request direct connection. 24 | /// Requested user. 25 | /// Address of requested user. 26 | [SecuritySafeCritical] 27 | public ServerIntroduceConnectionsAction(UserId senderId, IPEndPoint senderPoint, UserId requestId, IPEndPoint requestPoint) 28 | { 29 | _senderId = senderId; 30 | _senderPoint = senderPoint; 31 | _requestId = requestId; 32 | _requestPoint = requestPoint; 33 | } 34 | 35 | [SecuritySafeCritical] 36 | public void Perform() 37 | { 38 | using (var server = ServerModel.Get()) 39 | { 40 | var senderUser = server.Chat.GetUser(_senderId); 41 | var certiticate = ServerModel.Server.GetCertificate(_senderId); 42 | var content = new ClientWaitPeerConnectionCommand.MessageContent 43 | { 44 | RequestIpAddress = _requestPoint.Address.GetAddressBytes(), 45 | RequestPort = _requestPoint.Port, 46 | SenderIpAddress = _senderPoint.Address.GetAddressBytes(), 47 | SenderPort = _senderPoint.Port, 48 | RemoteInfo = new UserDto(senderUser, certiticate.RawData), 49 | }; 50 | 51 | ServerModel.Server.SendMessage(_requestId, ClientWaitPeerConnectionCommand.CommandId, content); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Engine/Api/Server/P2P/ServerP2PConnectRequestCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Server.Messages; 4 | using Engine.Model.Common.Entities; 5 | using Engine.Model.Server; 6 | using ThirtyNineEighty.BinarySerializer; 7 | 8 | namespace Engine.Api.Server.P2P 9 | { 10 | [SecurityCritical] 11 | class ServerP2PConnectRequestCommand : 12 | ServerCommand 13 | { 14 | public const long CommandId = (long)ServerCommandId.P2PConnectRequest; 15 | 16 | public override long Id 17 | { 18 | [SecuritySafeCritical] 19 | get { return CommandId; } 20 | } 21 | 22 | [SecuritySafeCritical] 23 | protected override void OnRun(MessageContent content, CommandArgs args) 24 | { 25 | if (content.UserId == UserId.Empty) 26 | throw new ArgumentException("content.Nick"); 27 | 28 | if (!ServerModel.Server.ContainsConnection(content.UserId)) 29 | { 30 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.P2PUserNotExist)); 31 | return; 32 | } 33 | 34 | ServerModel.Server.P2PService.Introduce(args.ConnectionId, content.UserId); 35 | } 36 | 37 | [Serializable] 38 | [BinType("ServerP2PConnectRequest")] 39 | public class MessageContent 40 | { 41 | [BinField("n")] 42 | public UserId UserId; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Engine/Api/Server/P2P/ServerP2PReadyAcceptCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Client.P2P; 4 | using Engine.Api.Server.Messages; 5 | using Engine.Model.Common.Dto; 6 | using Engine.Model.Common.Entities; 7 | using Engine.Model.Server; 8 | using ThirtyNineEighty.BinarySerializer; 9 | 10 | namespace Engine.Api.Server.P2P 11 | { 12 | [SecurityCritical] 13 | class ServerP2PReadyAcceptCommand : 14 | ServerCommand 15 | { 16 | public const long CommandId = (long)ServerCommandId.P2PReadyAccept; 17 | 18 | public override long Id 19 | { 20 | [SecuritySafeCritical] 21 | get { return CommandId; } 22 | } 23 | 24 | [SecuritySafeCritical] 25 | protected override void OnRun(MessageContent content, CommandArgs args) 26 | { 27 | if (content.RemoteInfo == null) 28 | throw new ArgumentNullException("content.RemoteInfo"); 29 | 30 | if (!ServerModel.Server.ContainsConnection(content.ReceiverId)) 31 | { 32 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.P2PUserNotExist)); 33 | return; 34 | } 35 | 36 | var connectContent = new ClientConnectToPeerCommand.MessageContent 37 | { 38 | Port = content.PeerPort, 39 | IPAddress = content.PeerIPAddress, 40 | RemoteInfo = content.RemoteInfo 41 | }; 42 | 43 | ServerModel.Server.SendMessage(content.ReceiverId, ClientConnectToPeerCommand.CommandId, connectContent); 44 | } 45 | 46 | [Serializable] 47 | [BinType("ServerP2PReadyAccept")] 48 | public class MessageContent 49 | { 50 | [BinField("r")] 51 | public UserId ReceiverId; 52 | 53 | [BinField("p")] 54 | public int PeerPort; 55 | 56 | [BinField("a")] 57 | public byte[] PeerIPAddress; 58 | 59 | [BinField("u")] 60 | public UserDto RemoteInfo; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Engine/Api/Server/P2P/ServerSendP2PConnectRequestAction.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api.Client.P2P; 2 | using Engine.Model.Common.Entities; 3 | using Engine.Model.Server; 4 | using System; 5 | using System.Security; 6 | 7 | namespace Engine.Api.Server.P2P 8 | { 9 | [Serializable] 10 | public class ServerSendP2PConnectRequestAction : IAction 11 | { 12 | private readonly UserId _userId; 13 | private readonly int _servicePort; 14 | 15 | /// 16 | /// Send request to user for connection to P2PService. 17 | /// 18 | /// User who recive connection request. 19 | /// P2PService port. 20 | [SecuritySafeCritical] 21 | public ServerSendP2PConnectRequestAction(UserId userId, int servicePort) 22 | { 23 | _userId = userId; 24 | _servicePort = servicePort; 25 | } 26 | 27 | [SecuritySafeCritical] 28 | public void Perform() 29 | { 30 | var sendingContent = new ClientConnectToP2PServiceCommand.MessageContent { Port = _servicePort }; 31 | ServerModel.Server.SendMessage(_userId, ClientConnectToP2PServiceCommand.CommandId, sendingContent); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Engine/Api/Server/Registrations/ServerUnregisterCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | using Engine.Model.Server; 3 | 4 | namespace Engine.Api.Server.Registrations 5 | { 6 | [SecurityCritical] 7 | class ServerUnregisterCommand : ServerCommand 8 | { 9 | public const long CommandId = (long)ServerCommandId.Unregister; 10 | 11 | public override long Id 12 | { 13 | [SecuritySafeCritical] 14 | get { return CommandId; } 15 | } 16 | 17 | [SecuritySafeCritical] 18 | protected override void OnRun(CommandArgs args) 19 | { 20 | ServerModel.Api.Perform(new ServerRemoveUserAction(args.ConnectionId)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Engine/Api/Server/Rooms/ServerCreateRoomCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Client.Rooms; 4 | using Engine.Api.Server.Messages; 5 | using Engine.Model.Common.Entities; 6 | using Engine.Model.Server; 7 | using Engine.Model.Server.Entities; 8 | using ThirtyNineEighty.BinarySerializer; 9 | 10 | namespace Engine.Api.Server.Rooms 11 | { 12 | [SecurityCritical] 13 | class ServerCreateRoomCommand : 14 | ServerCommand 15 | { 16 | public const long CommandId = (long)ServerCommandId.CreateRoom; 17 | 18 | public override long Id 19 | { 20 | [SecuritySafeCritical] 21 | get { return CommandId; } 22 | } 23 | 24 | [SecuritySafeCritical] 25 | protected override void OnRun(MessageContent content, CommandArgs args) 26 | { 27 | if (string.IsNullOrEmpty(content.RoomName)) 28 | throw new ArgumentNullException("content.RoomName"); 29 | 30 | using(var server = ServerModel.Get()) 31 | { 32 | if (server.Chat.IsRoomExist(content.RoomName)) 33 | { 34 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomAlreadyExist)); 35 | return; 36 | } 37 | 38 | Room room = null; 39 | if (content.Type == RoomType.Chat) 40 | { 41 | var textRoom = new ServerRoom(args.ConnectionId, content.RoomName); 42 | server.Chat.AddRoom(textRoom); 43 | room = textRoom; 44 | } 45 | 46 | if (content.Type == RoomType.Voice) 47 | { 48 | var voiceRoom = new ServerVoiceRoom(args.ConnectionId, content.RoomName); 49 | server.Chat.AddVoiceRoom(voiceRoom); 50 | room = voiceRoom; 51 | } 52 | 53 | if (room == null) 54 | throw new ArgumentException("content.RoomType"); 55 | 56 | var sendingContent = new ClientRoomOpenedCommand.MessageContent 57 | { 58 | Room = room.ToDto(args.ConnectionId), 59 | Users = server.Chat.GetRoomUserDtos(room.Name) 60 | }; 61 | 62 | ServerModel.Server.SendMessage(args.ConnectionId, ClientRoomOpenedCommand.CommandId, sendingContent); 63 | } 64 | } 65 | 66 | [Serializable] 67 | [BinType("ServerCreateRoom")] 68 | public class MessageContent 69 | { 70 | [BinField("r")] 71 | public string RoomName; 72 | 73 | [BinField("t")] 74 | public RoomType Type; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Engine/Api/Server/Rooms/ServerDeleteRoomCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Client.Rooms; 4 | using Engine.Api.Server.Messages; 5 | using Engine.Model.Common.Entities; 6 | using Engine.Model.Server; 7 | using Engine.Model.Server.Entities; 8 | using ThirtyNineEighty.BinarySerializer; 9 | 10 | namespace Engine.Api.Server.Rooms 11 | { 12 | [SecurityCritical] 13 | class ServerDeleteRoomCommand : 14 | ServerCommand 15 | { 16 | public const long CommandId = (long)ServerCommandId.DeleteRoom; 17 | 18 | public override long Id 19 | { 20 | [SecuritySafeCritical] 21 | get { return CommandId; } 22 | } 23 | 24 | [SecuritySafeCritical] 25 | protected override void OnRun(MessageContent content, CommandArgs args) 26 | { 27 | if (string.IsNullOrEmpty(content.RoomName)) 28 | throw new ArgumentException("content.RoomName"); 29 | 30 | if (content.RoomName == ServerChat.MainRoomName) 31 | { 32 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomAccessDenied)); 33 | return; 34 | } 35 | 36 | using (var server = ServerModel.Get()) 37 | { 38 | Room deletingRoom; 39 | if (!TryGetRoom(server.Chat, content.RoomName, args.ConnectionId, out deletingRoom)) 40 | return; 41 | 42 | if (deletingRoom.Admin != args.ConnectionId) 43 | { 44 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomAccessDenied)); 45 | return; 46 | } 47 | 48 | server.Chat.RemoveRoom(content.RoomName); 49 | 50 | var sendingContent = new ClientRoomClosedCommand.MessageContent { RoomName = deletingRoom.Name }; 51 | foreach (var user in deletingRoom.Users) 52 | ServerModel.Server.SendMessage(user, ClientRoomClosedCommand.CommandId, sendingContent); 53 | } 54 | } 55 | 56 | [Serializable] 57 | [BinType("ServerDeleteRoom")] 58 | public class MessageContent 59 | { 60 | [BinField("r")] 61 | public string RoomName; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Engine/Api/Server/Rooms/ServerRefreshRoomCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Client.Rooms; 4 | using Engine.Api.Server.Messages; 5 | using Engine.Model.Common.Entities; 6 | using Engine.Model.Server; 7 | using ThirtyNineEighty.BinarySerializer; 8 | 9 | namespace Engine.Api.Server.Rooms 10 | { 11 | [SecurityCritical] 12 | class ServerRefreshRoomCommand : 13 | ServerCommand 14 | { 15 | public const long CommandId = (long)ServerCommandId.RefreshRoom; 16 | 17 | public override long Id 18 | { 19 | [SecuritySafeCritical] 20 | get { return CommandId; } 21 | } 22 | 23 | [SecuritySafeCritical] 24 | protected override void OnRun(MessageContent content, CommandArgs args) 25 | { 26 | if (string.IsNullOrEmpty(content.RoomName)) 27 | throw new ArgumentException("content.RoomName"); 28 | 29 | using (var server = ServerModel.Get()) 30 | { 31 | Room room; 32 | if (!TryGetRoom(server.Chat, content.RoomName, args.ConnectionId, out room)) 33 | return; 34 | 35 | if (!room.IsUserExist(args.ConnectionId)) 36 | { 37 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomAccessDenied)); 38 | return; 39 | } 40 | 41 | var roomRefreshedContent = new ClientRoomRefreshedCommand.MessageContent 42 | { 43 | Room = room.ToDto(args.ConnectionId), 44 | Users = server.Chat.GetRoomUserDtos(room.Name) 45 | }; 46 | 47 | ServerModel.Server.SendMessage(args.ConnectionId, ClientRoomRefreshedCommand.CommandId, roomRefreshedContent); 48 | } 49 | } 50 | 51 | [Serializable] 52 | [BinType("ServerRefreshRoom")] 53 | public class MessageContent 54 | { 55 | [BinField("r")] 56 | public string RoomName; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Engine/Api/Server/Rooms/ServerSetRoomAdminCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using Engine.Api.Server.Messages; 4 | using Engine.Model.Common.Entities; 5 | using Engine.Model.Server; 6 | using Engine.Model.Server.Entities; 7 | using ThirtyNineEighty.BinarySerializer; 8 | 9 | namespace Engine.Api.Server.Rooms 10 | { 11 | [SecurityCritical] 12 | class ServerSetRoomAdminCommand : 13 | ServerCommand 14 | { 15 | public const long CommandId = (long)ServerCommandId.SetRoomAdmin; 16 | 17 | public override long Id 18 | { 19 | [SecuritySafeCritical] 20 | get { return CommandId; } 21 | } 22 | 23 | [SecuritySafeCritical] 24 | protected override void OnRun(MessageContent content, CommandArgs args) 25 | { 26 | if (string.IsNullOrEmpty(content.RoomName)) 27 | throw new ArgumentException("content.RoomName"); 28 | 29 | if (content.RoomName == ServerChat.MainRoomName) 30 | { 31 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomAccessDenied)); 32 | return; 33 | } 34 | 35 | using (var server = ServerModel.Get()) 36 | { 37 | Room room; 38 | if (!TryGetRoom(server.Chat, content.RoomName, args.ConnectionId, out room)) 39 | return; 40 | 41 | if (room.Admin != args.ConnectionId) 42 | { 43 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomAccessDenied)); 44 | return; 45 | } 46 | 47 | if (!room.IsUserExist(content.NewAdmin)) 48 | { 49 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(args.ConnectionId, SystemMessageId.RoomUserNotExist)); 50 | return; 51 | } 52 | 53 | room.Admin = content.NewAdmin; 54 | ServerModel.Api.Perform(new ServerSendSystemMessageAction(content.NewAdmin, SystemMessageId.RoomAdminChanged, room.Name)); 55 | } 56 | } 57 | 58 | [Serializable] 59 | [BinType("ServerSetRoomAdmin")] 60 | public class MessageContent 61 | { 62 | [BinField("r")] 63 | public string RoomName; 64 | 65 | [BinField("a")] 66 | public UserId NewAdmin; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Engine/Api/Server/ServerCommandId.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Api.Server 2 | { 3 | // TODO: rus 4 | //Команды для сервера: (формат сообщений XX XX Serialized(this.MessageContent)) 5 | //Расшифровка XX XX: 6 | //8 00 00: Запрос регистрации (в главной комнате) 7 | //8 00 01: Запрос выхода (из всех комнат) 8 | 9 | //8 00 10: Отправка сообщения всем клиентам в комнате 10 | //8 00 11: Отправка личного сообщения конкретному юзеру 11 | 12 | //8 00 20: Запрос открытого пароля пользователя 13 | 14 | //8 00 30: Создать комнату 15 | //8 00 31: Удалить комнату 16 | //8 00 32: Пригласить пользователей в комнату 17 | //8 00 33: Кикнуть пользователей из комнаты 18 | //8 00 34: Выйти из комнаты 19 | //8 00 35: Запрос обновления комнаты 20 | //8 00 36: Сделать пользователя администратором комнаты 21 | 22 | //8 00 40: Пинг запрос 23 | 24 | //8 00 50: Добавить файл на раздачу комнаты 25 | //8 00 51: Удалить файл с раздачи комнаты 26 | 27 | //8 00 60: Запрос прямого соединения 28 | //8 00 61: Ответ, говорящий о готовности принять входное содеинение 29 | 30 | //8 00 70: Text admin command 31 | 32 | //8 7F FF: Пустая команда 33 | 34 | enum ServerCommandId : long 35 | { 36 | Register = 0x80000, 37 | Unregister = 0x80001, 38 | 39 | SendRoomMessage = 0x80010, 40 | SendPrivateMessage = 0x80011, 41 | 42 | GetUserOpenKeyRequest = 0x80020, 43 | 44 | CreateRoom = 0x80030, 45 | DeleteRoom = 0x80031, 46 | InvateUsers = 0x80032, 47 | KickUsers = 0x80033, 48 | ExitFromRoom = 0x80034, 49 | RefreshRoom = 0x80035, 50 | SetRoomAdmin = 0x80036, 51 | 52 | PingRequest = 0x80040, 53 | 54 | AddFileToRoom = 0x80050, 55 | RemoveFileFromRoom = 0x80051, 56 | 57 | P2PConnectRequest = 0x80060, 58 | P2PReadyAccept = 0x80061, 59 | 60 | Admin = 0x80070, 61 | 62 | Empty = 0x87FFF 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Engine/Audio/IPlayer.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Engine.Audio 6 | { 7 | // TODO: rus 8 | public interface IPlayer : IDisposable 9 | { 10 | /// 11 | /// Устанавливает устройство воспроизводящее звук. 12 | /// 13 | /// Имя устройства. 14 | void SetOptions(string deviceName); 15 | 16 | /// 17 | /// Ставит в очередь на воспроизведение массив звуковых данных, для пользователя. 18 | /// 19 | /// Id пользователя. 20 | /// 21 | /// Номер пакета. 22 | /// Если меньше чем текущий воспроизведенный, пакет воспроизведен не будет. 23 | /// 24 | /// Пакет с данными о записи. 25 | void Enqueue(UserId id, long packNumber, SoundPack pack); 26 | 27 | /// 28 | /// Оставноить воспроизведение для пользователя. 29 | /// 30 | /// Id Пользователя. 31 | void Stop(UserId id); 32 | 33 | /// 34 | /// Остановить воспроизведение. 35 | /// 36 | void Stop(); 37 | 38 | /// 39 | /// Возвращает заначение говоряеще о том инциализирован ли класс. 40 | /// 41 | bool IsInited { get; } 42 | 43 | /// 44 | /// Возвращает список утросйств воспроизводящих звук. 45 | /// 46 | IList Devices { get; } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Engine/Audio/IRecorder.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Engine.Audio 6 | { 7 | public interface IRecorder : IDisposable 8 | { 9 | /// 10 | /// Происходит при заполнении буффера. 11 | /// 12 | event EventHandler Recorded; 13 | 14 | /// 15 | /// Устанавливает настройки качества записи. И устройство записывающее звук. 16 | /// 17 | /// Имя устройства. 18 | /// Количество записи. 19 | void SetOptions(string deviceName, AudioQuality quality); 20 | 21 | /// 22 | /// Запускает запись с микрофона. 23 | /// 24 | void Start(); 25 | 26 | /// 27 | /// Останавливает запись с микрофона. 28 | /// 29 | void Stop(); 30 | 31 | /// 32 | /// Возвращает заначение говоряеще о том инциализирован ли класс. 33 | /// 34 | bool IsInited { get; } 35 | 36 | /// 37 | /// Возвращает список утросйств записывающих звук. 38 | /// 39 | IList Devices { get; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Engine/EngineStrongName.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aoaydin/TCPChat/245d8caadd3dc7884bae06afc00b03fa81905e73/Engine/EngineStrongName.snk -------------------------------------------------------------------------------- /Engine/EventArgs/AsyncErrorEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine 4 | { 5 | [Serializable] 6 | public class AsyncErrorEventArgs : EventArgs 7 | { 8 | public Exception Error { get; private set; } 9 | 10 | public AsyncErrorEventArgs(Exception e) 11 | { 12 | Error = e; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Engine/EventArgs/ConnectEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Engine.Network; 2 | using System; 3 | 4 | namespace Engine 5 | { 6 | [Serializable] 7 | public class ConnectEventArgs : EventArgs 8 | { 9 | public Exception Error { get; private set; } 10 | 11 | public ConnectEventArgs() 12 | { 13 | } 14 | 15 | public ConnectEventArgs(Exception e) 16 | { 17 | Error = e; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Engine/EventArgs/ConnectionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | 4 | namespace Engine 5 | { 6 | [Serializable] 7 | public class ConnectionEventArgs : EventArgs 8 | { 9 | public UserId Id { get; private set; } 10 | 11 | public ConnectionEventArgs(UserId id) 12 | { 13 | Id = id; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Engine/EventArgs/FileDownloadEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | 4 | namespace Engine 5 | { 6 | [Serializable] 7 | public class FileDownloadEventArgs : EventArgs 8 | { 9 | public string RoomName { get; private set; } 10 | public FileId FileId { get; private set; } 11 | 12 | public int Progress { get; private set; } 13 | 14 | public FileDownloadEventArgs(string roomName, FileId fileId, int progress) 15 | { 16 | RoomName = roomName; 17 | FileId = fileId; 18 | Progress = progress; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Engine/EventArgs/PackageReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Engine.Network; 2 | using System; 3 | 4 | namespace Engine 5 | { 6 | [Serializable] 7 | public class PackageReceivedEventArgs : EventArgs 8 | { 9 | public Unpacked Unpacked { get; private set; } 10 | public Exception Exception { get; private set; } 11 | 12 | public PackageReceivedEventArgs(Unpacked unpacked) 13 | { 14 | Unpacked = unpacked; 15 | } 16 | 17 | public PackageReceivedEventArgs(Exception e) 18 | { 19 | Exception = e; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Engine/EventArgs/PackageSendedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine 4 | { 5 | [Serializable] 6 | public class PackageSendedEventArgs : EventArgs 7 | { 8 | public int Size { get; private set; } 9 | public Exception Exception { get; private set; } 10 | 11 | public PackageSendedEventArgs(int size) 12 | { 13 | Size = size; 14 | } 15 | 16 | public PackageSendedEventArgs(Exception e) 17 | { 18 | Exception = e; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Engine/EventArgs/PluginEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine 4 | { 5 | [Serializable] 6 | public class PluginEventArgs : EventArgs 7 | { 8 | public string PluginName { get; private set; } 9 | 10 | public PluginEventArgs(string pluginName) 11 | { 12 | PluginName = pluginName; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Engine/EventArgs/ReceiveMessageEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | 4 | namespace Engine 5 | { 6 | [Serializable] 7 | public class ReceiveMessageEventArgs : EventArgs 8 | { 9 | public long MessageId { get; set; } 10 | public MessageType Type { get; set; } 11 | public DateTime Time { get; set; } 12 | 13 | public UserId Sender { get; set; } 14 | public string RoomName { get; set; } 15 | 16 | public string Message { get; set; } 17 | 18 | public SystemMessageId SystemMessage { get; set; } 19 | public string[] SystemMessageFormat { get; set; } 20 | 21 | public FileId FileId { get; set; } 22 | } 23 | 24 | public enum MessageType 25 | { 26 | Common, 27 | Private, 28 | System, 29 | File 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Engine/EventArgs/RecordedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine 4 | { 5 | [Serializable] 6 | public class RecordedEventArgs : EventArgs 7 | { 8 | public byte[] Data { get; private set; } 9 | public int DataSize { get; private set; } 10 | public int Channels { get; private set; } 11 | public int BitPerChannel { get; private set; } 12 | public int Frequency { get; private set; } 13 | 14 | public RecordedEventArgs(byte[] data, int availableData, int channels, int bits, int frequency) 15 | { 16 | Data = data; 17 | DataSize = availableData * channels * (bits / 8); 18 | Channels = channels; 19 | BitPerChannel = bits; 20 | Frequency = frequency; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Engine/EventArgs/RegistrationEventArgs.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | 4 | namespace Engine 5 | { 6 | [Serializable] 7 | public class RegistrationEventArgs : EventArgs 8 | { 9 | public bool Registered { get; set; } 10 | public SystemMessageId Message { get; set; } 11 | 12 | public RegistrationEventArgs(bool registered, SystemMessageId message) 13 | { 14 | Registered = registered; 15 | Message = message; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Engine/EventArgs/RoomClosedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine 4 | { 5 | [Serializable] 6 | public class RoomClosedEventArgs : EventArgs 7 | { 8 | public string RoomName { get; private set; } 9 | 10 | public RoomClosedEventArgs(string roomName) 11 | { 12 | RoomName = roomName; 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /Engine/EventArgs/RoomOpenedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine 4 | { 5 | [Serializable] 6 | public class RoomOpenedEventArgs : EventArgs 7 | { 8 | public string RoomName { get; private set; } 9 | 10 | public RoomOpenedEventArgs(string roomName) 11 | { 12 | RoomName = roomName; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Engine/EventArgs/RoomRefreshedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Engine 5 | { 6 | [Serializable] 7 | public class RoomRefreshedEventArgs : EventArgs 8 | { 9 | public string RoomName { get; private set; } 10 | public HashSet AddedMessages { get; private set; } 11 | public HashSet RemovedMessages { get; private set; } 12 | 13 | public RoomRefreshedEventArgs(string roomName, HashSet addedMessages, HashSet removedMessages) 14 | { 15 | RoomName = roomName; 16 | AddedMessages = addedMessages; 17 | RemovedMessages = removedMessages; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Engine/EventArgs/RoomUsersEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine 4 | { 5 | public class RoomUsersEventArgs : EventArgs 6 | { 7 | public string Nick { get; private set; } 8 | public bool Removed { get; private set; } 9 | 10 | public RoomUsersEventArgs(string nick, bool removed) 11 | { 12 | Nick = nick; 13 | Removed = removed; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Engine/EventArgs/TrustedCertificatesEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography.X509Certificates; 3 | 4 | namespace Engine 5 | { 6 | public class TrustedCertificatesEventArgs : EventArgs 7 | { 8 | public X509Certificate2 Certificate { get; private set; } 9 | public bool Removed { get; private set; } 10 | 11 | public TrustedCertificatesEventArgs(X509Certificate2 cert, bool removed) 12 | { 13 | Certificate = cert; 14 | Removed = removed; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Engine/Exceptions/ErrorCode.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Exceptions 2 | { 3 | public enum ErrorCode 4 | { 5 | ApiNotSupported = 1, 6 | FileAlreadyDownloading = 2, 7 | FreePortDontFound = 3, 8 | LargeReceivedData = 4, 9 | CantDownloadOwnFile = 5, 10 | 11 | AudioNotEnabled = 100, 12 | 13 | PluginError = 200, 14 | 15 | RoomNotFound = 300, 16 | FileInRoomNotFound = 301, 17 | UnknownRoomType = 302, 18 | 19 | WrongContentType = 1000, 20 | IllegalInvoker = 1001 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Engine/Exceptions/ModelException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine.Exceptions 4 | { 5 | [Serializable] 6 | public class ModelException : Exception 7 | { 8 | public ErrorCode Code { get; private set; } 9 | public object State { get; private set; } 10 | 11 | public ModelException(ErrorCode code, string message, Exception inner, object state = null) 12 | : base(message, inner) 13 | { 14 | Code = code; 15 | State = state; 16 | } 17 | 18 | public ModelException(ErrorCode code, string message, object state = null) 19 | : base(message) 20 | { 21 | Code = code; 22 | State = state; 23 | } 24 | 25 | public ModelException(ErrorCode code, object state = null) 26 | : this(code, code.ToString(), state) 27 | { 28 | 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Engine/Helpers/EventDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine.Helpers 4 | { 5 | internal static class EventDispatcher 6 | { 7 | public static void BeginDispatch(this EventHandler handler, object sender, T args, Action onEnd) 8 | where T: EventArgs 9 | { 10 | if (handler != null) 11 | ArgsDispatcher.BeginDispatch(handler, sender, args, onEnd); 12 | else 13 | { 14 | if (onEnd != null) 15 | onEnd(null); 16 | } 17 | } 18 | 19 | private static class ArgsDispatcher 20 | where T : EventArgs 21 | { 22 | private class State 23 | { 24 | public readonly EventHandler Invoked; 25 | public readonly Action OnEnd; 26 | 27 | public State(EventHandler invoked, Action onEnd) 28 | { 29 | Invoked = invoked; 30 | OnEnd = onEnd; 31 | } 32 | } 33 | 34 | public static void BeginDispatch(EventHandler handler, object sender, T args, Action onEnd) 35 | { 36 | handler.BeginInvoke(sender, args, EndDispatch, new State(handler, onEnd)); 37 | } 38 | 39 | private static void EndDispatch(IAsyncResult result) 40 | { 41 | Exception exception = null; 42 | var state = (State)result.AsyncState; 43 | try 44 | { 45 | state.Invoked.EndInvoke(result); 46 | } 47 | catch (Exception e) 48 | { 49 | exception = e; 50 | } 51 | finally 52 | { 53 | if (state.OnEnd != null) 54 | state.OnEnd(exception); 55 | } 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Engine/Helpers/Serializer.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Security; 3 | using System.Security.Permissions; 4 | using ThirtyNineEighty.BinarySerializer; 5 | 6 | namespace Engine.Helpers 7 | { 8 | public static class Serializer 9 | { 10 | [SecuritySafeCritical] 11 | [PermissionSet(SecurityAction.Assert, Unrestricted = true)] 12 | public static byte[] Serialize(T obj) 13 | { 14 | using (MemoryStream stream = new MemoryStream()) 15 | { 16 | BinSerializer.Serialize(stream, obj); 17 | return stream.ToArray(); 18 | } 19 | } 20 | 21 | [SecuritySafeCritical] 22 | [PermissionSet(SecurityAction.Assert, Unrestricted = true)] 23 | public static void Serialize(Stream stream, T obj) 24 | { 25 | BinSerializer.Serialize(stream, obj); 26 | } 27 | 28 | [SecuritySafeCritical] 29 | [PermissionSet(SecurityAction.Assert, Unrestricted = true)] 30 | public static T Deserialize(byte[] message) 31 | { 32 | using (MemoryStream stream = new MemoryStream(message)) 33 | return BinSerializer.Deserialize(stream); 34 | } 35 | 36 | [SecuritySafeCritical] 37 | [PermissionSet(SecurityAction.Assert, Unrestricted = true)] 38 | public static T Deserialize(Stream stream) 39 | { 40 | return BinSerializer.Deserialize(stream); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Engine/Helpers/TryLock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Engine.Helpers 5 | { 6 | public struct TryLock : IDisposable 7 | { 8 | private volatile bool _lockTaken; 9 | private readonly object _syncObject; 10 | 11 | public TryLock(object obj, int timeout = 10000) 12 | { 13 | _syncObject = obj; 14 | _lockTaken = Monitor.TryEnter(_syncObject, timeout); 15 | if (!_lockTaken) 16 | throw new InvalidOperationException("TryEnterLock timeout"); 17 | } 18 | 19 | public void Dispose() 20 | { 21 | if (_lockTaken) 22 | Monitor.Exit(_syncObject); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Engine/Model/Client/ClientCertificatesStorage.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography.X509Certificates; 2 | using Engine.Helpers; 3 | using Engine.Model.Common; 4 | 5 | namespace Engine.Model.Client 6 | { 7 | public class ClientCertificatesStorage : CertificatesStorage 8 | { 9 | private readonly IClientNotifier _notifier; 10 | 11 | public ClientCertificatesStorage(string path, IClientNotifier notifier, Logger logger) 12 | : base(path, logger) 13 | { 14 | _notifier = notifier; 15 | } 16 | 17 | protected override void OnAdded(X509Certificate2 certificate) 18 | { 19 | base.OnAdded(certificate); 20 | _notifier.TrustedCertificatesChanged(new TrustedCertificatesEventArgs(certificate, false)); 21 | } 22 | 23 | protected override void OnRemoved(X509Certificate2 certificate) 24 | { 25 | base.OnRemoved(certificate); 26 | _notifier.TrustedCertificatesChanged(new TrustedCertificatesEventArgs(certificate, true)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Engine/Model/Client/ClientGuard.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Client.Entities; 2 | using System.Security; 3 | 4 | namespace Engine.Model.Client 5 | { 6 | public class ClientGuard : Guard 7 | { 8 | [SecurityCritical] 9 | public ClientGuard(ClientChat chat) 10 | : base(chat) 11 | { 12 | 13 | } 14 | 15 | public ClientChat Chat 16 | { 17 | get { return _obj; } 18 | } 19 | 20 | public static ClientChat CurrentChat 21 | { 22 | [SecuritySafeCritical] 23 | get { return ((ClientGuard)_current).Chat; } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Engine/Model/Client/ClientInitializer.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Security.Cryptography.X509Certificates; 3 | 4 | namespace Engine.Model.Client 5 | { 6 | public class ClientInitializer 7 | { 8 | public string Nick { get; set; } 9 | public Color NickColor { get; set; } 10 | public X509Certificate2 Certificate { get; set; } 11 | public string TrustedCertificatesPath { get; set; } 12 | 13 | public string PluginsPath { get; set; } 14 | public string[] ExcludedPlugins { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Engine/Model/Client/Entities/ClientRoom.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Dto; 2 | using Engine.Model.Common.Entities; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Model.Client.Entities 7 | { 8 | [Serializable] 9 | public class ClientRoom : Room 10 | { 11 | [SecuritySafeCritical] 12 | public ClientRoom(RoomDto dto) 13 | : base(dto.Admin, dto.Name) 14 | { 15 | foreach (var nick in dto.Users) 16 | _users.Add(nick); 17 | 18 | foreach (var file in dto.Files) 19 | _files.Add(file.Id, new FileDescription(file)); 20 | 21 | foreach (var message in dto.Messages) 22 | _messages.Add(message.Id, new Message(message)); 23 | } 24 | 25 | #region files 26 | [SecuritySafeCritical] 27 | public override bool RemoveFile(FileId fileId) 28 | { 29 | var result = base.RemoveFile(fileId); 30 | if (result) 31 | { 32 | var chat = ClientGuard.CurrentChat; 33 | 34 | // Remove downloading 35 | if (chat.IsFileDownloading(fileId)) 36 | chat.RemoveFileDownload(fileId); 37 | 38 | // Notify 39 | var downloadEventArgs = new FileDownloadEventArgs(Name, fileId, 0); 40 | ClientModel.Notifier.PostedFileDeleted(downloadEventArgs); 41 | } 42 | return result; 43 | } 44 | #endregion 45 | 46 | #region dispose 47 | protected override void ReleaseManagedResources() 48 | { 49 | base.ReleaseManagedResources(); 50 | 51 | // Remove all posted files. 52 | var chat = ClientGuard.CurrentChat; 53 | foreach (var file in Files) 54 | { 55 | if (file.Id.Owner == chat.User.Id) 56 | chat.RemovePostedFile(Name, file.Id); 57 | } 58 | } 59 | #endregion 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Engine/Model/Client/Entities/ClientUser.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Dto; 2 | using Engine.Model.Common.Entities; 3 | using System; 4 | using System.Drawing; 5 | using System.Security; 6 | using System.Security.Cryptography.X509Certificates; 7 | 8 | namespace Engine.Model.Client.Entities 9 | { 10 | [Serializable] 11 | public class ClientUser : User 12 | { 13 | private int _voiceCounter; 14 | private X509Certificate2 _certificate; 15 | 16 | /// 17 | /// Creates new instance of user. 18 | /// 19 | /// User id. 20 | /// Nick color. 21 | /// User certificate. 22 | [SecuritySafeCritical] 23 | public ClientUser(UserId id, Color color, X509Certificate2 certificate) 24 | : base(id, color) 25 | { 26 | _certificate = certificate; 27 | } 28 | 29 | /// 30 | /// Creates new instance of user. 31 | /// 32 | /// Data transfer object of user. 33 | [SecuritySafeCritical] 34 | public ClientUser(UserDto dto) 35 | : base(dto) 36 | { 37 | _certificate = new X509Certificate2(dto.Certificate); 38 | } 39 | 40 | /// 41 | /// User certificate. 42 | /// 43 | public X509Certificate2 Certificate 44 | { 45 | [SecuritySafeCritical] 46 | get { return _certificate; } 47 | } 48 | 49 | /// 50 | /// Checks is voice active for user. 51 | /// 52 | /// Returns true if voice active, otherwise false. 53 | [SecuritySafeCritical] 54 | public bool IsVoiceActive() 55 | { 56 | return _voiceCounter > 0; 57 | } 58 | 59 | /// 60 | /// Increments voice counter. 61 | /// Counter used to check voice state (enabled/disabled). 62 | /// 63 | [SecuritySafeCritical] 64 | public void IncVoiceCounter() 65 | { 66 | _voiceCounter++; 67 | } 68 | 69 | /// 70 | /// Decrements voice counter. 71 | /// Counter used to check voice state (enabled/disabled). 72 | /// 73 | [SecuritySafeCritical] 74 | public void DecVoiceCounter() 75 | { 76 | if (_voiceCounter == 0) 77 | throw new InvalidOperationException("Can't decrement voice counter."); 78 | _voiceCounter--; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Engine/Model/Common/Dto/BinNullable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ThirtyNineEighty.BinarySerializer; 3 | 4 | namespace Engine.Model.Common.Dto 5 | { 6 | /// 7 | /// Represents nullable type for BinarySerializer 8 | /// 9 | [Serializable] 10 | [BinType("BinNullable")] 11 | public sealed class BinNullable 12 | where T: struct 13 | { 14 | [BinField("v")] 15 | public T Value; 16 | 17 | public BinNullable(T value) 18 | { 19 | Value = value; 20 | } 21 | 22 | public static implicit operator T?(BinNullable nullable) 23 | { 24 | return nullable == null ? (T?)null : nullable.Value; 25 | } 26 | 27 | public static implicit operator BinNullable(T value) 28 | { 29 | return new BinNullable(value); 30 | } 31 | 32 | public static implicit operator BinNullable(T? value) 33 | { 34 | if (value == null) 35 | return null; 36 | return new BinNullable(value.Value); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Engine/Model/Common/Dto/ColorDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using ThirtyNineEighty.BinarySerializer; 4 | 5 | namespace Engine.Model.Common.Dto 6 | { 7 | [Serializable] 8 | [BinType("ColorDto")] 9 | public class ColorDto 10 | { 11 | [BinField("r")] 12 | public byte Red; 13 | 14 | [BinField("g")] 15 | public byte Green; 16 | 17 | [BinField("b")] 18 | public byte Blue; 19 | 20 | public ColorDto() 21 | { 22 | } 23 | 24 | public ColorDto(Color color) 25 | { 26 | Red = color.R; 27 | Green = color.G; 28 | Blue = color.B; 29 | } 30 | 31 | public Color ToColor() 32 | { 33 | return Color.FromArgb(Red, Green, Blue); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Engine/Model/Common/Dto/FileDescriptionDto.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | using ThirtyNineEighty.BinarySerializer; 4 | 5 | namespace Engine.Model.Common.Dto 6 | { 7 | /// 8 | /// File description data transfer object. 9 | /// 10 | [Serializable] 11 | [BinType("FileDescriptionDto")] 12 | public class FileDescriptionDto 13 | { 14 | [BinField("i")] 15 | public FileId Id; 16 | 17 | [BinField("s")] 18 | public long Size; 19 | 20 | [BinField("n")] 21 | public string Name; 22 | 23 | public FileDescriptionDto(FileDescription file) 24 | : this(file.Id, file.Size, file.Name) 25 | { 26 | 27 | } 28 | 29 | public FileDescriptionDto(FileId id, long size, string name) 30 | { 31 | Id = id; 32 | Size = size; 33 | Name = name; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Engine/Model/Common/Dto/MessageDto.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | using ThirtyNineEighty.BinarySerializer; 4 | 5 | namespace Engine.Model.Common.Dto 6 | { 7 | /// 8 | /// Message data transfer object. 9 | /// 10 | [Serializable] 11 | [BinType("MessageDto")] 12 | public class MessageDto 13 | { 14 | [BinField("i")] 15 | public long Id; 16 | 17 | [BinField("t")] 18 | public DateTime Time; 19 | 20 | [BinField("x")] 21 | public string Text; 22 | 23 | [BinField("o")] 24 | public UserId Owner; 25 | 26 | public MessageDto(Message msg) 27 | { 28 | Id = msg.Id; 29 | Time = msg.Time; 30 | Text = msg.Text; 31 | Owner = msg.Owner; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Engine/Model/Common/Dto/RoomDto.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using ThirtyNineEighty.BinarySerializer; 6 | 7 | namespace Engine.Model.Common.Dto 8 | { 9 | /// 10 | /// Room data transfer object. 11 | /// 12 | [Serializable] 13 | [BinType("RoomDto")] 14 | public class RoomDto 15 | { 16 | [BinField("n")] 17 | public string Name; 18 | 19 | [BinField("a")] 20 | public UserId Admin; 21 | 22 | [BinField("u")] 23 | public UserId[] Users; 24 | 25 | [BinField("f")] 26 | public FileDescriptionDto[] Files; 27 | 28 | [BinField("m")] 29 | public MessageDto[] Messages; 30 | 31 | [BinField("t")] 32 | public RoomType Type; 33 | 34 | [BinField("c")] 35 | public UserId[] ConnectTo; 36 | 37 | public RoomDto( 38 | string name 39 | , UserId admin 40 | , IEnumerable users 41 | , IEnumerable files 42 | , IEnumerable messages 43 | , RoomType type 44 | , IEnumerable connectTo) 45 | { 46 | Name = name; 47 | Admin = admin; 48 | Users = users.ToArray(); 49 | Files = files.Select(f => f.ToDto()).ToArray(); 50 | Messages = messages.Select(m => m.ToDto()).ToArray(); 51 | 52 | Type = type; 53 | 54 | if (connectTo != null) 55 | ConnectTo = connectTo.ToArray(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Engine/Model/Common/Dto/UserDto.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Client.Entities; 2 | using Engine.Model.Common.Entities; 3 | using System; 4 | using System.Drawing; 5 | using System.Security.Cryptography.X509Certificates; 6 | using ThirtyNineEighty.BinarySerializer; 7 | 8 | namespace Engine.Model.Common.Dto 9 | { 10 | /// 11 | /// User data transfer object. 12 | /// 13 | [Serializable] 14 | [BinType("UserDto", Version = 2)] 15 | public class UserDto 16 | { 17 | [BinField("n")] 18 | public UserId Id; 19 | 20 | [BinField("c")] 21 | public ColorDto NickColor; 22 | 23 | [BinField("i")] 24 | public byte[] Certificate; 25 | 26 | public UserDto(User user, byte[] certificate) 27 | : this(user.Id, user.NickColor, certificate) 28 | { 29 | } 30 | 31 | public UserDto(ClientUser user) 32 | : this(user, user.Certificate.Export(X509ContentType.Cert)) 33 | { 34 | 35 | } 36 | 37 | public UserDto(UserId id, Color color, byte[] certificate) 38 | { 39 | Id = id; 40 | NickColor = new ColorDto(color); 41 | Certificate = certificate; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/AudioQuality.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | 4 | namespace Engine.Model.Common.Entities 5 | { 6 | [Serializable] 7 | public class AudioQuality : IEquatable 8 | { 9 | public int Channels { get; set; } 10 | public int Bits { get; set; } 11 | public int Frequency { get; set; } 12 | 13 | [SecuritySafeCritical] 14 | public AudioQuality(int channels, int bits, int frequency) 15 | { 16 | if (channels != 2 && channels != 1) 17 | throw new ArgumentException("channels"); 18 | 19 | if (bits != 8 && bits != 16) 20 | throw new ArgumentException("bitPerChannel"); 21 | 22 | if (frequency <= 0) 23 | throw new ArgumentException("frequency"); 24 | 25 | Channels = channels; 26 | Bits = bits; 27 | Frequency = frequency; 28 | } 29 | 30 | [SecuritySafeCritical] 31 | public override string ToString() 32 | { 33 | return string.Format("{0} bits / {1} Hz", Bits, Frequency); 34 | } 35 | 36 | [SecuritySafeCritical] 37 | public override bool Equals(object obj) 38 | { 39 | if (obj is null) 40 | return false; 41 | 42 | if (ReferenceEquals(obj, this)) 43 | return true; 44 | 45 | var quality = obj as AudioQuality; 46 | if (quality is null) 47 | return false; 48 | 49 | return Equals(quality); 50 | } 51 | 52 | [SecuritySafeCritical] 53 | public bool Equals(AudioQuality other) 54 | { 55 | if (other is null) 56 | return false; 57 | 58 | if (ReferenceEquals(other, this)) 59 | return true; 60 | 61 | return Channels == other.Channels && 62 | Bits == other.Bits && 63 | Frequency == other.Frequency; 64 | } 65 | 66 | [SecuritySafeCritical] 67 | public override int GetHashCode() 68 | { 69 | int hashCode = Channels; 70 | hashCode = (hashCode ^ 397) * Bits; 71 | hashCode = (hashCode ^ 397) * Frequency; 72 | return hashCode; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/DownloadingFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Security; 4 | 5 | namespace Engine.Model.Common.Entities 6 | { 7 | public sealed class DownloadingFile : 8 | MarshalByRefObject, 9 | IDisposable 10 | { 11 | private bool _disposed = false; 12 | 13 | /// 14 | /// File Description. 15 | /// 16 | public FileDescription File 17 | { 18 | [SecuritySafeCritical] 19 | get; 20 | [SecurityCritical] 21 | private set; 22 | } 23 | 24 | /// 25 | /// Saving file stream. 26 | /// 27 | public FileStream WriteStream 28 | { 29 | [SecuritySafeCritical] 30 | get; 31 | [SecurityCritical] 32 | private set; 33 | } 34 | 35 | /// 36 | /// Path where file stored. 37 | /// 38 | public string FullName 39 | { 40 | [SecuritySafeCritical] 41 | get; 42 | [SecurityCritical] 43 | private set; 44 | } 45 | 46 | /// 47 | /// Create the instance of DownloadingFile. 48 | /// 49 | /// File description. 50 | /// Path where the file will be stored on disc. 51 | [SecuritySafeCritical] 52 | public DownloadingFile(FileDescription file, string fullName) 53 | { 54 | File = file; 55 | FullName = fullName; 56 | WriteStream = new FileStream(fullName, FileMode.Create, FileAccess.Write); 57 | } 58 | 59 | /// 60 | /// Dispose the resources of DownloadingFile. 61 | /// 62 | [SecuritySafeCritical] 63 | public void Dispose() 64 | { 65 | if (_disposed) 66 | return; 67 | 68 | _disposed = true; 69 | 70 | if (WriteStream != null) 71 | { 72 | WriteStream.Dispose(); 73 | WriteStream = null; 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/FileId.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using ThirtyNineEighty.BinarySerializer; 4 | 5 | namespace Engine.Model.Common.Entities 6 | { 7 | [Serializable] 8 | [BinType("FieldIdDto")] 9 | public struct FileId : IEquatable 10 | { 11 | [BinField("i")] 12 | private int _id; 13 | 14 | [BinField("o")] 15 | private UserId _owner; 16 | 17 | /// 18 | /// Create file identification. 19 | /// 20 | /// File identificator. 21 | /// File owner user id. 22 | [SecuritySafeCritical] 23 | public FileId(int id, UserId owner) 24 | { 25 | _id = id; 26 | _owner = owner; 27 | } 28 | 29 | /// 30 | /// File identificator. 31 | /// 32 | public int Id { get { return _id; } } 33 | 34 | /// 35 | /// File owner user id. 36 | /// 37 | public UserId Owner { get { return _owner; } } 38 | 39 | [SecuritySafeCritical] 40 | public static bool operator == (FileId first, FileId second) 41 | { 42 | return first.Equals(second); 43 | } 44 | 45 | [SecuritySafeCritical] 46 | public static bool operator != (FileId first, FileId second) 47 | { 48 | return !first.Equals(second); 49 | } 50 | 51 | [SecuritySafeCritical] 52 | public override bool Equals(object obj) 53 | { 54 | if (obj == null) 55 | return false; 56 | if (!(obj is FileId)) 57 | return false; 58 | return Equals((FileId)obj); 59 | } 60 | 61 | [SecuritySafeCritical] 62 | public bool Equals(FileId other) 63 | { 64 | return Id == other.Id && Owner == other.Owner; 65 | } 66 | 67 | [SecuritySafeCritical] 68 | public override int GetHashCode() 69 | { 70 | return (Id * 397) ^ Owner.GetHashCode(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/Message.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Dto; 2 | using System; 3 | using System.Security; 4 | 5 | namespace Engine.Model.Common.Entities 6 | { 7 | /// 8 | /// User message. 9 | /// 10 | [Serializable] 11 | public class Message 12 | { 13 | /// 14 | /// Message id. 15 | /// 16 | public readonly long Id; 17 | 18 | /// 19 | /// Message sender. 20 | /// 21 | public readonly UserId Owner; 22 | 23 | /// 24 | /// Time when message was sent. 25 | /// 26 | public readonly DateTime Time; 27 | 28 | /// 29 | /// Message text. 30 | /// 31 | public string Text; 32 | 33 | [SecuritySafeCritical] 34 | public Message(MessageDto dto) 35 | : this(dto.Id, dto.Owner, dto.Text, dto.Time) 36 | { 37 | 38 | } 39 | 40 | [SecuritySafeCritical] 41 | public Message(long id, UserId owner, string text) 42 | : this(id, owner, text, DateTime.UtcNow) 43 | { 44 | } 45 | 46 | [SecuritySafeCritical] 47 | public Message(long id, UserId owner, string text, DateTime time) 48 | { 49 | Owner = owner; 50 | Id = id; 51 | Text = text; 52 | Time = time; 53 | } 54 | 55 | /// 56 | /// Trying to concat other message with this. 57 | /// 58 | /// Other message which trying to contact with this. 59 | /// If result is true then message was concated, otherwise - false. 60 | [SecuritySafeCritical] 61 | public bool TryConcat(Message other) 62 | { 63 | if (Owner != other.Owner) 64 | return false; 65 | 66 | const double ConcatMinutes = 1; 67 | if ((other.Time - Time).TotalMinutes > ConcatMinutes) 68 | return false; 69 | 70 | Text += string.Format("{0}{1}", Environment.NewLine, other.Text); 71 | return true; 72 | } 73 | 74 | [SecuritySafeCritical] 75 | public MessageDto ToDto() 76 | { 77 | return new MessageDto(this); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/RoomType.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Model.Common.Entities 2 | { 3 | public enum RoomType 4 | { 5 | Unknown = -1, 6 | Chat = 1, 7 | Voice = 2, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/SoundPack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ThirtyNineEighty.BinarySerializer; 3 | 4 | namespace Engine.Model.Common.Entities 5 | { 6 | /// 7 | /// Recorderd voice data. 8 | /// 9 | [Serializable] 10 | [BinType("SoundPackDto")] 11 | public class SoundPack 12 | { 13 | /// 14 | /// Recorded data. 15 | /// 16 | [BinField("d")] 17 | public byte[] Data; 18 | 19 | /// 20 | /// Channels count. 21 | /// 22 | [BinField("c")] 23 | public int Channels; 24 | 25 | /// 26 | /// Pits per channel count. 27 | /// 28 | [BinField("b")] 29 | public int BitPerChannel; 30 | 31 | /// 32 | /// Frequency. 33 | /// 34 | [BinField("f")] 35 | public int Frequency; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/SystemMessageId.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Model.Common.Entities 2 | { 3 | // TODO: rus 4 | public enum SystemMessageId 5 | { 6 | None = 0, 7 | 8 | ApiNotSupported = 1, // Api not supperted by server. 9 | ConnectionRetryAttempt = 2, // Connection retry attempt... 10 | 11 | NotRegisteredBadName = 10, // Connection cant be registered with this nick. Invalid characters. 12 | NotRegisteredNameAlreadyExist = 11, // Connection cant be registered with this nick. Nick already exist. 13 | NotRegisteredBadThumbprint = 12, // Connection cant be registered. User id thumbprint does not match certificate. 14 | 15 | RoomAdminChanged = 20, // Вы назначены администратором комнаты. {0} - название команаты. 16 | RoomAccessDenied = 21, // Вы не входите в состав этой комнаты. 17 | RoomAlreadyExist = 22, // Комната с таким именем уже создана, выберите другое имя. 18 | RoomCantLeaveMainRoom = 23, // Невозможно выйти из основной комнаты. 19 | RoomItsMainRoom = 24, // Невозможно произвести это действие с основной комнатой. 20 | RoomNotExist = 25, // Команата с таким именем не существует. 21 | RoomUserNotExist = 26, // Такого пользователя нет в комнате. 22 | 23 | FileRemoveAccessDenied = 30, // Вы не можете удалить данный файл. Не хватает прав. 24 | FileRemoved = 31, // Файл удален {0} - имя файла. 25 | 26 | MessageEditAccessDenied = 40, // Вы не можете редактировать это сообщение. 27 | 28 | P2PUserNotExist = 50, // Данного пользователя не существует. 29 | 30 | InvalidPassword = 60, // Invalid password. 31 | TextCommandNotFound = 61, // Text command not found. 32 | TextCommandsList = 62, // Text commands list. 33 | TextCommandInvalidParams = 63, // Text command params are invalid 34 | TextCommandMessageId = 64, // Result of showMessageId command 35 | TextCommandUsersList = 65 // Result with user ids 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/User.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Dto; 2 | using System; 3 | using System.Drawing; 4 | using System.Security; 5 | 6 | namespace Engine.Model.Common.Entities 7 | { 8 | // TODO: add dispose 9 | [Serializable] 10 | public class User : 11 | IEquatable 12 | { 13 | private readonly UserId _id; 14 | private readonly Color _nickColor; 15 | 16 | /// 17 | /// Creates new instance of user. 18 | /// 19 | /// User id. 20 | /// Nick color. 21 | [SecuritySafeCritical] 22 | public User(UserId id, Color nickColor) 23 | { 24 | _id = id; 25 | _nickColor = nickColor; 26 | } 27 | 28 | /// 29 | /// Creates new instance of user. 30 | /// 31 | /// Data transfer object of user. 32 | [SecuritySafeCritical] 33 | public User(UserDto dto) 34 | { 35 | _id = dto.Id; 36 | _nickColor = dto.NickColor.ToColor(); 37 | } 38 | 39 | /// 40 | /// User id. 41 | /// 42 | public UserId Id 43 | { 44 | [SecuritySafeCritical] 45 | get { return _id; } 46 | } 47 | 48 | /// 49 | /// Nick color. 50 | /// 51 | public Color NickColor 52 | { 53 | [SecuritySafeCritical] 54 | get { return _nickColor; } 55 | } 56 | 57 | [SecuritySafeCritical] 58 | public override bool Equals(object obj) 59 | { 60 | if (obj is null) 61 | return false; 62 | 63 | if (ReferenceEquals(obj, this)) 64 | return true; 65 | 66 | var user = obj as User; 67 | if (user is null) 68 | return false; 69 | 70 | return Equals(user); 71 | } 72 | 73 | [SecuritySafeCritical] 74 | public override int GetHashCode() 75 | { 76 | return _id.GetHashCode(); 77 | } 78 | 79 | [SecuritySafeCritical] 80 | public bool Equals(User user) 81 | { 82 | if (user is null) 83 | return false; 84 | 85 | if (ReferenceEquals(user, this)) 86 | return true; 87 | 88 | return Equals(_id, user.Id); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Engine/Model/Common/Entities/VoiceRoom.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Security; 4 | 5 | namespace Engine.Model.Common.Entities 6 | { 7 | [Serializable] 8 | public class VoiceRoom : Room 9 | { 10 | /// 11 | /// Create new voice room instance. 12 | /// 13 | /// Admin nick. 14 | /// Room name. 15 | [SecuritySafeCritical] 16 | public VoiceRoom(UserId admin, string name) 17 | : base(admin, name) 18 | { 19 | 20 | } 21 | 22 | /// 23 | /// Create new voice room instance. 24 | /// 25 | /// Admin nick. 26 | /// Room name. 27 | /// Initial room users list. 28 | [SecuritySafeCritical] 29 | public VoiceRoom(UserId admin, string name, IEnumerable initialUsers) 30 | : base(admin, name, initialUsers) 31 | { 32 | 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Engine/Model/Common/Guard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using System.Threading; 4 | 5 | namespace Engine.Model 6 | { 7 | public abstract class Guard : MarshalByRefObject, IDisposable 8 | where T : class 9 | { 10 | #if DEBUG 11 | private const int TimeOut = -1; 12 | #else 13 | private const int TimeOut = 10000; 14 | #endif 15 | 16 | [ThreadStatic] protected static Guard _current; 17 | protected T _obj; 18 | 19 | [SecurityCritical] 20 | protected Guard(T obj) 21 | { 22 | if (!Monitor.TryEnter(obj, TimeOut)) 23 | throw new InvalidOperationException("model lock timeout"); 24 | 25 | _obj = obj; 26 | 27 | if (_current == null) 28 | _current = this; 29 | } 30 | 31 | [SecuritySafeCritical] 32 | public void Dispose() 33 | { 34 | if (_current == this) 35 | _current = null; 36 | 37 | var obj = _obj; 38 | _obj = default; 39 | 40 | Monitor.Exit(obj); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Engine/Model/Server/Entities/ServerChat.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Dto; 2 | using Engine.Model.Common.Entities; 3 | using System; 4 | using System.Linq; 5 | using System.Security; 6 | 7 | namespace Engine.Model.Server.Entities 8 | { 9 | [Serializable] 10 | public class ServerChat : Chat 11 | { 12 | [SecurityCritical] 13 | public ServerChat() 14 | { 15 | AddRoom(new ServerRoom(UserId.Empty, MainRoomName)); 16 | } 17 | 18 | #region users 19 | /// 20 | /// Returns all users from room as dtos. 21 | /// 22 | /// Room name. 23 | [SecuritySafeCritical] 24 | public UserDto[] GetRoomUserDtos(string roomName) 25 | { 26 | var room = GetRoom(roomName); 27 | return room.Users 28 | .Select(CreateDto) 29 | .ToArray(); 30 | } 31 | 32 | [SecuritySafeCritical] 33 | private UserDto CreateDto(UserId userId) 34 | { 35 | var user = GetUser(userId); 36 | var certificate = ServerModel.Server.GetCertificate(userId); 37 | return new UserDto(user, certificate.RawData); 38 | } 39 | #endregion 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Engine/Model/Server/Entities/ServerRoom.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security; 6 | 7 | namespace Engine.Model.Server.Entities 8 | { 9 | [Serializable] 10 | public class ServerRoom : Room 11 | { 12 | /// 13 | /// Create the room. 14 | /// 15 | /// User id which be administrator of the room. 16 | /// Room name. 17 | [SecuritySafeCritical] 18 | public ServerRoom(UserId admin, string name) 19 | : base(admin, name) 20 | { 21 | 22 | } 23 | 24 | /// 25 | /// Create the room. 26 | /// 27 | /// User id which be administrator of the room. 28 | /// Room name. 29 | /// Initial room users list. 30 | [SecuritySafeCritical] 31 | public ServerRoom(UserId admin, string name, IEnumerable initialUsers) 32 | : base(admin, name, initialUsers) 33 | { 34 | 35 | } 36 | 37 | #region users 38 | [SecuritySafeCritical] 39 | public IEnumerable GetUsers() 40 | { 41 | return _users.Select(n => ServerGuard.Current.GetUser(n)); 42 | } 43 | #endregion 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Engine/Model/Server/ServerGuard.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Server.Entities; 2 | using System.Security; 3 | 4 | namespace Engine.Model.Server 5 | { 6 | public class ServerGuard : Guard 7 | { 8 | [SecurityCritical] 9 | public ServerGuard(ServerChat chat) 10 | : base(chat) 11 | { 12 | 13 | } 14 | 15 | public ServerChat Chat 16 | { 17 | [SecuritySafeCritical] 18 | get { return _obj; } 19 | } 20 | 21 | public static ServerChat Current 22 | { 23 | [SecuritySafeCritical] 24 | get { return ((ServerGuard)_current).Chat; } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Engine/Model/Server/ServerInitializer.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography.X509Certificates; 2 | 3 | namespace Engine.Model.Server 4 | { 5 | public class ServerInitializer 6 | { 7 | public string AdminPassword { get; set; } 8 | public string PluginsPath { get; set; } 9 | public string[] ExcludedPlugins { get; set; } 10 | public X509Certificate2 Certificate { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Engine/Model/Server/ServerNotifier.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security; 6 | 7 | namespace Engine.Model.Server 8 | { 9 | [SecuritySafeCritical] 10 | public class ServerNotifier : Notifier 11 | { 12 | [SecuritySafeCritical] 13 | public override IEnumerable GetEvents() 14 | { 15 | var events = base.GetEvents(); 16 | return events.Concat(ServerModel.Plugins.GetNotifierEvents()); 17 | } 18 | } 19 | 20 | [Notifier(typeof(IServerEvents), BaseNotifier = typeof(ServerNotifier))] 21 | public interface IServerNotifier : INotifier 22 | { 23 | void StartError(AsyncErrorEventArgs args); 24 | 25 | void ConnectionOpened(ConnectionEventArgs args); 26 | void ConnectionClosing(ConnectionEventArgs args, Action callback); 27 | void ConnectionClosed(ConnectionEventArgs args); 28 | 29 | void ConnectionRegistered(ConnectionEventArgs args); 30 | void ConnectionUnregistered(ConnectionEventArgs args); 31 | } 32 | 33 | public interface IServerEvents 34 | { 35 | event EventHandler StartError; 36 | 37 | event EventHandler ConnectionOpened; 38 | event EventHandler ConnectionClosing; 39 | event EventHandler ConnectionClosed; 40 | 41 | event EventHandler ConnectionRegistered; 42 | event EventHandler ConnectionUnregistered; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Engine/Network/CertificateStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Network 2 | { 3 | public enum CertificateStatus 4 | { 5 | Unknown = 0, 6 | Untrusted = 1, 7 | Trusted = 2, 8 | SelfSigned = 3, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Engine/Network/ConnectionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ThirtyNineEighty.BinarySerializer; 3 | 4 | namespace Engine.Network 5 | { 6 | public enum AlgorithmId 7 | { 8 | Aes256CBC = 0 9 | } 10 | 11 | [Serializable] 12 | [BinType("ServerConnectionInfo", Version = 3)] 13 | public class ServerInfo 14 | { 15 | [BinField("a")] 16 | public string ApiName; 17 | [BinField("c")] 18 | public byte[] RawX509Certificate; 19 | } 20 | 21 | [Serializable] 22 | [BinType("HandshakeRequest", Version = 2)] 23 | public class HandshakeRequest 24 | { 25 | [BinField("c")] 26 | public byte[] RawX509Certificate; 27 | 28 | [BinField("a")] 29 | public AlgorithmId AlgorithmId; 30 | 31 | [BinField("k")] 32 | public byte[] EncryptedKey; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Engine/Network/Package.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | using ThirtyNineEighty.BinarySerializer; 4 | 5 | namespace Engine.Network 6 | { 7 | public interface IPackage 8 | { 9 | long Id { get; } 10 | } 11 | 12 | public interface IPackage : IPackage 13 | { 14 | T Content { get; } 15 | } 16 | 17 | [Serializable] 18 | [BinType("PackageDto")] 19 | [SecuritySafeCritical] 20 | public class Package : IPackage 21 | { 22 | [BinField("i")] 23 | private long _id; 24 | 25 | [SecuritySafeCritical] 26 | public Package(long id) 27 | { 28 | _id = id; 29 | } 30 | 31 | public long Id 32 | { 33 | get { return _id; } 34 | } 35 | } 36 | 37 | [Serializable] 38 | [BinType("PackageTDto")] 39 | [SecuritySafeCritical] 40 | public class Package : Package, IPackage 41 | { 42 | [BinField("c")] 43 | private T _content; 44 | 45 | [SecuritySafeCritical] 46 | public Package(long id, T content) 47 | : base(id) 48 | { 49 | _content = content; 50 | } 51 | 52 | public T Content { get { return _content; } } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Engine/Network/Packed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.Serialization; 4 | using System.Security; 5 | using System.Security.Permissions; 6 | 7 | namespace Engine.Network 8 | { 9 | [Serializable] 10 | public struct Packed : IPoolable, ISerializable 11 | { 12 | private readonly Packer _owner; 13 | private readonly MemoryStream _stream; 14 | private readonly byte[] _data; 15 | 16 | public byte[] Data 17 | { 18 | [SecuritySafeCritical] 19 | get { return _data ?? _stream.GetBuffer(); } 20 | } 21 | 22 | public int Length 23 | { 24 | [SecuritySafeCritical] 25 | get 26 | { 27 | if (_data != null) 28 | return _data.Length; 29 | return (int)_stream.Length; 30 | } 31 | } 32 | 33 | MemoryStream IPoolable.Stream 34 | { 35 | [SecuritySafeCritical] 36 | get { return _stream; } 37 | } 38 | 39 | [SecurityCritical] 40 | public Packed(Packer owner, MemoryStream stream) 41 | { 42 | _owner = owner; 43 | _stream = stream; 44 | _data = null; 45 | } 46 | 47 | [SecurityCritical] 48 | public Packed(byte[] data) 49 | { 50 | _owner = null; 51 | _stream = null; 52 | _data = data; 53 | } 54 | 55 | [SecurityCritical] 56 | private Packed(SerializationInfo info, StreamingContext context) 57 | { 58 | _owner = null; 59 | _stream = null; 60 | _data = (byte[])info.GetValue("_data", typeof(byte[])); 61 | } 62 | 63 | [SecuritySafeCritical] 64 | public void Dispose() 65 | { 66 | if (_owner != null) 67 | _owner.Release(this); 68 | } 69 | 70 | [SecurityCritical] 71 | [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] 72 | public void GetObjectData(SerializationInfo info, StreamingContext context) 73 | { 74 | byte[] data; 75 | if (_data != null) 76 | data = _data; 77 | else 78 | { 79 | data = new byte[(int)_stream.Length]; 80 | Array.Copy(_stream.GetBuffer(), data, data.Length); 81 | } 82 | 83 | info.AddValue("_data", data, typeof(byte[])); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Engine/Network/ServerBans.cs: -------------------------------------------------------------------------------- 1 | using Engine.Model.Common.Entities; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Security; 5 | 6 | namespace Engine.Network 7 | { 8 | public class ServerBans 9 | { 10 | private readonly AsyncServer _server; 11 | 12 | private readonly object _syncObject = new object(); 13 | private readonly Dictionary _connectionIdToAddress = new Dictionary(); 14 | private readonly Dictionary _addressToConnectionId = new Dictionary(); 15 | 16 | [SecuritySafeCritical] 17 | public ServerBans(AsyncServer server) 18 | { 19 | _server = server; 20 | } 21 | 22 | [SecuritySafeCritical] 23 | public void Ban(UserId connectionId) 24 | { 25 | var ipAddress = _server.GetIp(connectionId); 26 | lock (_syncObject) 27 | { 28 | _connectionIdToAddress.Add(connectionId, ipAddress); 29 | _addressToConnectionId.Add(ipAddress, connectionId); 30 | } 31 | } 32 | 33 | [SecuritySafeCritical] 34 | public void Unban(UserId connectionId) 35 | { 36 | lock (_syncObject) 37 | { 38 | if (_connectionIdToAddress.TryGetValue(connectionId, out IPAddress address)) 39 | { 40 | _connectionIdToAddress.Remove(connectionId); 41 | _addressToConnectionId.Remove(address); 42 | } 43 | } 44 | } 45 | 46 | [SecuritySafeCritical] 47 | public bool IsBanned(UserId connectionId) 48 | { 49 | lock (_syncObject) 50 | return _connectionIdToAddress.ContainsKey(connectionId); 51 | } 52 | 53 | [SecuritySafeCritical] 54 | public bool IsBanned(IPAddress address) 55 | { 56 | lock (_syncObject) 57 | return _addressToConnectionId.ContainsKey(address); 58 | } 59 | 60 | [SecuritySafeCritical] 61 | public UserId Who(IPAddress address) 62 | { 63 | lock (_syncObject) 64 | { 65 | _addressToConnectionId.TryGetValue(address, out UserId connectionId); 66 | return connectionId; 67 | } 68 | } 69 | 70 | [SecuritySafeCritical] 71 | public List FindAll(string nick) 72 | { 73 | lock (_syncObject) 74 | { 75 | var result = new List(); 76 | foreach (var userId in _connectionIdToAddress.Keys) 77 | { 78 | if (string.Equals(userId.Nick, nick, System.StringComparison.Ordinal)) 79 | result.Add(userId); 80 | } 81 | return result; 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Engine/Plugins/Client/ClientModelWrapper.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api; 2 | using Engine.Audio; 3 | using Engine.Helpers; 4 | using Engine.Model.Client; 5 | using Engine.Network; 6 | using System.Security; 7 | 8 | namespace Engine.Plugins.Client 9 | { 10 | public class ClientModelWrapper : 11 | CrossDomainObject 12 | { 13 | public IApi Api 14 | { 15 | [SecuritySafeCritical] 16 | get { return ClientModel.Api; } 17 | } 18 | 19 | public AsyncClient Client 20 | { 21 | [SecuritySafeCritical] 22 | get { return ClientModel.Client; } 23 | } 24 | 25 | public AsyncPeer Peer 26 | { 27 | [SecuritySafeCritical] 28 | get { return ClientModel.Peer; } 29 | } 30 | 31 | public IPlayer Player 32 | { 33 | [SecuritySafeCritical] 34 | get { return ClientModel.Player; } 35 | } 36 | 37 | public IRecorder Recorder 38 | { 39 | [SecuritySafeCritical] 40 | get { return ClientModel.Recorder; } 41 | } 42 | 43 | public Logger Logger 44 | { 45 | [SecuritySafeCritical] 46 | get { return ClientModel.Logger; } 47 | } 48 | 49 | /// 50 | /// Исользовать только с конструкцией using 51 | /// 52 | /// using (var client = ClientModel.Get()) { ... } 53 | /// Возвращает и блокирует модель. 54 | [SecuritySafeCritical] 55 | public ClientGuard Get() { return ClientModel.Get(); } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Engine/Plugins/Client/ClientPlugin.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Plugins.Client 2 | { 3 | // TODO: rus 4 | /// 5 | /// Представляет базовый класс для реализации клиентского плагина. 6 | /// 7 | public abstract class ClientPlugin : 8 | Plugin 9 | { 10 | public abstract string MenuCaption { get; } 11 | public abstract void InvokeMenuHandler(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Engine/Plugins/Client/ClientPluginCommand.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api; 2 | using Engine.Api.Client; 3 | using Engine.Exceptions; 4 | using Engine.Helpers; 5 | using Engine.Network; 6 | 7 | namespace Engine.Plugins.Client 8 | { 9 | public abstract class ClientPluginCommand : ClientCommand 10 | { 11 | } 12 | 13 | public abstract class ClientPluginCommand : ClientPluginCommand 14 | { 15 | protected sealed override void OnRun(CommandArgs args) 16 | { 17 | var package = args.Unpacked.Package as IPackage; 18 | if (package == null) 19 | throw new ModelException(ErrorCode.WrongContentType); 20 | 21 | var content = Serializer.Deserialize(package.Content); 22 | OnRun(content, args); 23 | } 24 | 25 | protected abstract void OnRun(TContent content, CommandArgs args); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Engine/Plugins/Client/ClientPluginManager.cs: -------------------------------------------------------------------------------- 1 | using Engine.Exceptions; 2 | using Engine.Model.Client; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Plugins.Client 7 | { 8 | [SecurityCritical] 9 | public class ClientPluginManager : 10 | PluginManager 11 | { 12 | [SecurityCritical] 13 | public ClientPluginManager(string path) 14 | : base(path) 15 | { 16 | 17 | } 18 | 19 | [SecurityCritical] 20 | public ClientPlugin GetPlugin(string name) 21 | { 22 | lock (SyncObject) 23 | { 24 | PluginContainer container; 25 | if (Plugins.TryGetValue(name, out container)) 26 | return container.Plugin; 27 | 28 | return null; 29 | } 30 | } 31 | 32 | [SecurityCritical] 33 | protected override void OnPluginLoaded(PluginContainer loaded) 34 | { 35 | base.OnPluginLoaded(loaded); 36 | 37 | ClientModel.Notifier.PluginLoaded(new PluginEventArgs(loaded.Plugin.Name)); 38 | } 39 | 40 | [SecurityCritical] 41 | protected override void OnPluginUnlodaing(PluginContainer unloading) 42 | { 43 | base.OnPluginUnlodaing(unloading); 44 | 45 | ClientModel.Notifier.PluginUnloading(new PluginEventArgs(unloading.Plugin.Name)); 46 | } 47 | 48 | [SecurityCritical] 49 | protected override void OnError(string message, Exception e) 50 | { 51 | ClientModel.Logger.Write(new ModelException(ErrorCode.PluginError, string.Format("Error: {0}", message), e)); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Engine/Plugins/CrossDomainObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security; 3 | 4 | namespace Engine.Plugins 5 | { 6 | public abstract class CrossDomainObject : MarshalByRefObject 7 | { 8 | [SecurityCritical] 9 | public sealed override object InitializeLifetimeService() 10 | { 11 | return null; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Engine/Plugins/Plugin.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api; 2 | using System.Collections.Generic; 3 | 4 | namespace Engine.Plugins 5 | { 6 | public abstract class Plugin : CrossDomainObject 7 | where TModel : CrossDomainObject 8 | where TCommand : CrossDomainObject, ICommand 9 | { 10 | public static TModel Model { get; private set; } 11 | 12 | public void Initialize(TModel model) 13 | { 14 | Model = model; 15 | Initialize(); 16 | } 17 | 18 | public abstract string Name { get; } 19 | public abstract IEnumerable Commands { get; } 20 | public abstract object NotifierEvents { get; } 21 | 22 | protected abstract void Initialize(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Engine/Plugins/PluginInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Engine.Plugins 4 | { 5 | [Serializable] 6 | class PluginInfo 7 | { 8 | public string Name { get; set; } 9 | public string AssemblyPath { get; private set;} 10 | public string TypeName { get; private set; } 11 | 12 | public PluginInfo(string pluginAssemblyPath, string pluginTypeName) 13 | { 14 | AssemblyPath = pluginAssemblyPath; 15 | TypeName = pluginTypeName; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Engine/Plugins/Server/ServerModelWrapper.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api; 2 | using Engine.Helpers; 3 | using Engine.Model.Server; 4 | using Engine.Network; 5 | using System.Security; 6 | 7 | namespace Engine.Plugins.Server 8 | { 9 | public class ServerModelWrapper : 10 | CrossDomainObject 11 | { 12 | public IApi Api 13 | { 14 | [SecuritySafeCritical] 15 | get { return ServerModel.Api; } 16 | } 17 | 18 | public AsyncServer Server 19 | { 20 | [SecuritySafeCritical] 21 | get { return ServerModel.Server; } 22 | } 23 | 24 | public Logger Logger 25 | { 26 | [SecuritySafeCritical] 27 | get { return ServerModel.Logger; } 28 | } 29 | 30 | /// 31 | /// Исользовать только с конструкцией using 32 | /// 33 | /// using (var server = SeeverModel.Get()) { ... } 34 | /// Возвращает и блокирует модель. 35 | [SecuritySafeCritical] 36 | public ServerGuard Get() 37 | { 38 | return ServerModel.Get(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Engine/Plugins/Server/ServerPlugin.cs: -------------------------------------------------------------------------------- 1 | namespace Engine.Plugins.Server 2 | { 3 | // TODO: rus 4 | /// 5 | /// Представляет базовый класс для реализации серверного плагина. 6 | /// 7 | public abstract class ServerPlugin : 8 | Plugin 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Engine/Plugins/Server/ServerPluginCommand.cs: -------------------------------------------------------------------------------- 1 | using Engine.Api; 2 | using Engine.Api.Server; 3 | using Engine.Exceptions; 4 | using Engine.Helpers; 5 | using Engine.Network; 6 | 7 | namespace Engine.Plugins.Server 8 | { 9 | public abstract class ServerPluginCommand : ServerCommand 10 | { 11 | } 12 | 13 | public abstract class ServerPluginCommand : ServerPluginCommand 14 | { 15 | protected sealed override void OnRun(CommandArgs args) 16 | { 17 | var package = args.Unpacked.Package as IPackage; 18 | if (package == null) 19 | throw new ModelException(ErrorCode.WrongContentType); 20 | 21 | var content = Serializer.Deserialize(package.Content); 22 | OnRun(content, args); 23 | } 24 | 25 | protected abstract void OnRun(TContent content, CommandArgs args); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Engine/Plugins/Server/ServerPluginManager.cs: -------------------------------------------------------------------------------- 1 | using Engine.Exceptions; 2 | using Engine.Model.Server; 3 | using System; 4 | using System.Security; 5 | 6 | namespace Engine.Plugins.Server 7 | { 8 | [SecurityCritical] 9 | public class ServerPluginManager : 10 | PluginManager 11 | { 12 | [SecurityCritical] 13 | public ServerPluginManager(string path) 14 | : base(path) 15 | { 16 | 17 | } 18 | 19 | [SecurityCritical] 20 | protected override void OnError(string message, Exception e) 21 | { 22 | ServerModel.Logger.Write(new ModelException(ErrorCode.PluginError, string.Format("Error: {0}", message), e)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Engine/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | 5 | // Управление общими сведениями о сборке осуществляется с помощью 6 | // набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, 7 | // связанные со сборкой. 8 | [assembly: AssemblyTitle("Engine")] 9 | [assembly: AssemblyDescription("TCP Chat Engine")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("39-80")] 12 | [assembly: AssemblyProduct("TCP Chat Engine")] 13 | [assembly: AssemblyCopyright("Copyright © 39-80 2018")] 14 | [assembly: AssemblyTrademark("ThirtyNineEighty")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Параметр ComVisible со значением FALSE делает типы в сборке невидимыми 18 | // для COM-компонентов. Если требуется обратиться к типу в этой сборке через 19 | // COM, задайте атрибуту ComVisible значение TRUE для этого типа. 20 | [assembly: ComVisible(false)] 21 | 22 | // Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM 23 | [assembly: Guid("3aeed69f-2ab4-439b-8281-bf011dd483db")] 24 | 25 | // Сведения о версии сборки состоят из следующих четырех значений: 26 | // 27 | // Основной номер версии 28 | // Дополнительный номер версии 29 | // Номер построения 30 | // Редакция 31 | // 32 | // Можно задать все значения или принять номер построения и номер редакции по умолчанию, 33 | // используя "*", как показано ниже: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("5.1.0.0")] 36 | [assembly: AssemblyFileVersion("5.1.0.0")] 37 | 38 | [assembly: AllowPartiallyTrustedCallers] -------------------------------------------------------------------------------- /Engine/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Anton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Libraries/OpenAL.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aoaydin/TCPChat/245d8caadd3dc7884bae06afc00b03fa81905e73/Libraries/OpenAL.dll -------------------------------------------------------------------------------- /Lidgren.Network/Documentation/ChangedFromV2.txt: -------------------------------------------------------------------------------- 1 |  2 | 3 | * The NetBuffer object is gone; instead there are NetOutgoingMessage and NetIncomingMessage objects 4 | 5 | * No need to allocate a read buffer before calling ReadMessage 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lidgren.Network/Documentation/Improvements.txt: -------------------------------------------------------------------------------- 1 |  2 | Improvements over last version of library: 3 | 4 | * New delivery type: Reliable sequenced (Lost packets are resent but late arrivals are dropped) 5 | * Disconnects and shutdown requests are now queued properly, so calling shutdown will still send any queued messages before shutting down 6 | * All messages are pooled/recycled for zero garbage 7 | * Reduced CPU usage and lower latencies (in the <1 ms range, but still) due to better socket polling 8 | * All public members of NetPeer/NetConnection are completely thread safe 9 | * Larger number of delivery channels 10 | * More exact roundtrip measurement 11 | * Method serialize entire objects via reflection 12 | * Unique identifier now exists for all peers/connections 13 | * More flexible peer discovery; filters possible and arbitrary data can be sent with response 14 | * Much better protection against malformed messages crashing the app 15 | 16 | API enhancements: 17 | * NetPeerConfiguration immutable properties now locked once NetPeer is initialized 18 | * Messages cannot be send twice by accident 19 | * Impossible to confuse sending and receiving buffers since they're different classes 20 | * No more confusion if user should create a buffer or preallocate and reuse 21 | 22 | 23 | -------------------------------------------------------------------------------- /Lidgren.Network/Documentation/PacketLayout.txt: -------------------------------------------------------------------------------- 1 |  2 | PER MESSAGE: 3 | 7 bits - NetMessageType 4 | 1 bit - Is a message fragment? 5 | 6 | [8 bits NetMessageLibraryType, if NetMessageType == Library] 7 | 8 | [16 bits sequence number, if NetMessageType >= UserSequenced] 9 | 10 | 8/16 bits - Payload length in bits (variable size ushort) 11 | 12 | [16 bits fragments group id, if fragmented] 13 | [16 bits fragments total count, if fragmented] 14 | [16 bits fragment number, if fragmented] 15 | 16 | [x - Payload] if length > 0 17 | 18 | -------------------------------------------------------------------------------- /Lidgren.Network/Documentation/TODO.txt: -------------------------------------------------------------------------------- 1 |  2 | Completed features: 3 | * Message coalescing 4 | * Peer, connection statistics 5 | * Lag, loss and duplication simulation for testing 6 | * Connection approval 7 | * Throttling 8 | * Clock synchronization to detect jitter per packet (NetTime.RemoteNow) 9 | * Peer discovery 10 | * Message fragmentation 11 | 12 | Missing features: 13 | * Receipts 25% done, need design 14 | * More realistic lag/loss (lumpy) 15 | * Detect estimated packet loss 16 | * More advanced ack packet 17 | 18 | -------------------------------------------------------------------------------- /Lidgren.Network/Encryption/INetEncryption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Lidgren.Network 5 | { 6 | /// 7 | /// Interface for an encryption algorithm 8 | /// 9 | public interface INetEncryption 10 | { 11 | /// 12 | /// Encrypt an outgoing message in place 13 | /// 14 | bool Encrypt(NetOutgoingMessage msg); 15 | 16 | /// 17 | /// Decrypt an incoming message in place 18 | /// 19 | bool Decrypt(NetIncomingMessage msg); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Lidgren.Network/Encryption/NetXorEncryption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Lidgren.Network 6 | { 7 | /// 8 | /// Example class; not very good encryption 9 | /// 10 | public class NetXorEncryption : INetEncryption 11 | { 12 | private byte[] m_key; 13 | 14 | /// 15 | /// NetXorEncryption constructor 16 | /// 17 | public NetXorEncryption(byte[] key) 18 | { 19 | m_key = key; 20 | } 21 | 22 | /// 23 | /// NetXorEncryption constructor 24 | /// 25 | public NetXorEncryption(string key) 26 | { 27 | m_key = Encoding.UTF8.GetBytes(key); 28 | } 29 | 30 | /// 31 | /// Encrypt an outgoing message 32 | /// 33 | public bool Encrypt(NetOutgoingMessage msg) 34 | { 35 | int numBytes = msg.LengthBytes; 36 | for (int i = 0; i < numBytes; i++) 37 | { 38 | int offset = i % m_key.Length; 39 | msg.m_data[i] = (byte)(msg.m_data[i] ^ m_key[offset]); 40 | } 41 | return true; 42 | } 43 | 44 | /// 45 | /// Decrypt an incoming message 46 | /// 47 | public bool Decrypt(NetIncomingMessage msg) 48 | { 49 | int numBytes = msg.LengthBytes; 50 | for (int i = 0; i < numBytes; i++) 51 | { 52 | int offset = i % m_key.Length; 53 | msg.m_data[i] = (byte)(msg.m_data[i] ^ m_key[offset]); 54 | } 55 | return true; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Lidgren.Network/LidgrenNetworkStrongName.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aoaydin/TCPChat/245d8caadd3dc7884bae06afc00b03fa81905e73/Lidgren.Network/LidgrenNetworkStrongName.snk -------------------------------------------------------------------------------- /Lidgren.Network/NamespaceDoc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Lidgren.Network 6 | { 7 | /// 8 | /// Lidgren Network Library 9 | /// 10 | internal class NamespaceDoc 11 | { 12 | // 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Lidgren.Network/NetConnectionStatus.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 Michael Lidgren 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without 5 | restriction, including without limitation the rights to use, copy, modify, merge, publish, 6 | distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom 7 | the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or 10 | substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 15 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 16 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 17 | USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | */ 19 | using System; 20 | 21 | namespace Lidgren.Network 22 | { 23 | /// 24 | /// Status for a NetConnection instance 25 | /// 26 | public enum NetConnectionStatus 27 | { 28 | /// 29 | /// No connection, or attempt, in place 30 | /// 31 | None, 32 | 33 | /// 34 | /// Connect has been sent; waiting for ConnectResponse 35 | /// 36 | InitiatedConnect, 37 | 38 | /// 39 | /// Connect was received, but ConnectResponse hasn't been sent yet 40 | /// 41 | ReceivedInitiation, 42 | 43 | /// 44 | /// Connect was received and ApprovalMessage released to the application; awaiting Approve() or Deny() 45 | /// 46 | RespondedAwaitingApproval, // We got Connect, released ApprovalMessage 47 | 48 | /// 49 | /// Connect was received and ConnectResponse has been sent; waiting for ConnectionEstablished 50 | /// 51 | RespondedConnect, // we got Connect, sent ConnectResponse 52 | 53 | /// 54 | /// Connected 55 | /// 56 | Connected, // we received ConnectResponse (if initiator) or ConnectionEstablished (if passive) 57 | 58 | /// 59 | /// In the process of disconnecting 60 | /// 61 | Disconnecting, 62 | 63 | /// 64 | /// Disconnected 65 | /// 66 | Disconnected 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Lidgren.Network/NetDeliveryMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Lidgren.Network 6 | { 7 | /// 8 | /// How the library deals with resends and handling of late messages 9 | /// 10 | public enum NetDeliveryMethod : byte 11 | { 12 | // 13 | // Actually a publicly visible subset of NetMessageType 14 | // 15 | 16 | /// 17 | /// Indicates an error 18 | /// 19 | Unknown = 0, 20 | 21 | /// 22 | /// Unreliable, unordered delivery 23 | /// 24 | Unreliable = 1, 25 | 26 | /// 27 | /// Unreliable delivery, but automatically dropping late messages 28 | /// 29 | UnreliableSequenced = 2, 30 | 31 | /// 32 | /// Reliable delivery, but unordered 33 | /// 34 | ReliableUnordered = 34, 35 | 36 | /// 37 | /// Reliable delivery, except for late messages which are dropped 38 | /// 39 | ReliableSequenced = 35, 40 | 41 | /// 42 | /// Reliable, ordered delivery 43 | /// 44 | ReliableOrdered = 67, 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Lidgren.Network/NetFragmentationInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | public sealed class NetFragmentationInfo 6 | { 7 | public int TotalFragmentCount; 8 | public bool[] Received; 9 | public int TotalReceived; 10 | public int FragmentSize; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Lidgren.Network/NetPeer.Discovery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace Lidgren.Network 5 | { 6 | public partial class NetPeer 7 | { 8 | /// 9 | /// Emit a discovery signal to all hosts on your subnet 10 | /// 11 | public void DiscoverLocalPeers(int serverPort) 12 | { 13 | NetOutgoingMessage om = CreateMessage(0); 14 | om.m_messageType = NetMessageType.Discovery; 15 | m_unsentUnconnectedMessages.Enqueue(new NetTuple(new IPEndPoint(IPAddress.Broadcast, serverPort), om)); 16 | } 17 | 18 | /// 19 | /// Emit a discovery signal to a single known host 20 | /// 21 | public bool DiscoverKnownPeer(string host, int serverPort) 22 | { 23 | IPAddress address = NetUtility.Resolve(host); 24 | if (address == null) 25 | return false; 26 | DiscoverKnownPeer(new IPEndPoint(address, serverPort)); 27 | return true; 28 | } 29 | 30 | /// 31 | /// Emit a discovery signal to a single known host 32 | /// 33 | public void DiscoverKnownPeer(IPEndPoint endPoint) 34 | { 35 | NetOutgoingMessage om = CreateMessage(0); 36 | om.m_messageType = NetMessageType.Discovery; 37 | m_unsentUnconnectedMessages.Enqueue(new NetTuple(endPoint, om)); 38 | } 39 | 40 | /// 41 | /// Send a discovery response message 42 | /// 43 | public void SendDiscoveryResponse(NetOutgoingMessage msg, IPEndPoint recipient) 44 | { 45 | if (recipient == null) 46 | throw new ArgumentNullException("recipient"); 47 | 48 | if (msg == null) 49 | msg = CreateMessage(0); 50 | else if (msg.m_isSent) 51 | throw new NetException("Message has already been sent!"); 52 | 53 | if (msg.LengthBytes >= m_configuration.MaximumTransmissionUnit) 54 | throw new NetException("Cannot send discovery message larger than MTU (currently " + m_configuration.MaximumTransmissionUnit + " bytes)"); 55 | 56 | msg.m_messageType = NetMessageType.DiscoveryResponse; 57 | m_unsentUnconnectedMessages.Enqueue(new NetTuple(recipient, msg)); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Lidgren.Network/NetPeerStatus.cs: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 Michael Lidgren 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without 5 | restriction, including without limitation the rights to use, copy, modify, merge, publish, 6 | distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom 7 | the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or 10 | substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 15 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 16 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 17 | USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | */ 20 | using System; 21 | 22 | namespace Lidgren.Network 23 | { 24 | /// 25 | /// Status for a NetPeer instance 26 | /// 27 | public enum NetPeerStatus 28 | { 29 | /// 30 | /// NetPeer is not running; socket is not bound 31 | /// 32 | NotRunning = 0, 33 | 34 | /// 35 | /// NetPeer is in the process of starting up 36 | /// 37 | Starting = 1, 38 | 39 | /// 40 | /// NetPeer is bound to socket and listening for packets 41 | /// 42 | Running = 2, 43 | 44 | /// 45 | /// Shutdown has been requested and will be executed shortly 46 | /// 47 | ShutdownRequested = 3, 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Lidgren.Network/NetReceiverChannelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | internal abstract class NetReceiverChannelBase 6 | { 7 | internal NetPeer m_peer; 8 | internal NetConnection m_connection; 9 | 10 | public NetReceiverChannelBase(NetConnection connection) 11 | { 12 | m_connection = connection; 13 | m_peer = connection.m_peer; 14 | } 15 | 16 | internal abstract void ReceiveMessage(NetIncomingMessage msg); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Lidgren.Network/NetReliableSequencedReceiver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | internal sealed class NetReliableSequencedReceiver : NetReceiverChannelBase 6 | { 7 | private int m_windowStart; 8 | private int m_windowSize; 9 | 10 | public NetReliableSequencedReceiver(NetConnection connection, int windowSize) 11 | : base(connection) 12 | { 13 | m_windowSize = windowSize; 14 | } 15 | 16 | private void AdvanceWindow() 17 | { 18 | m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers; 19 | } 20 | 21 | internal override void ReceiveMessage(NetIncomingMessage message) 22 | { 23 | int nr = message.m_sequenceNumber; 24 | 25 | int relate = NetUtility.RelativeSequenceNumber(nr, m_windowStart); 26 | 27 | // ack no matter what 28 | m_connection.QueueAck(message.m_receivedMessageType, nr); 29 | 30 | if (relate == 0) 31 | { 32 | // Log("Received message #" + message.SequenceNumber + " right on time"); 33 | 34 | // 35 | // excellent, right on time 36 | // 37 | 38 | AdvanceWindow(); 39 | m_peer.ReleaseMessage(message); 40 | return; 41 | } 42 | 43 | if (relate < 0) 44 | { 45 | m_peer.LogVerbose("Received message #" + message.m_sequenceNumber + " DROPPING LATE or DUPE"); 46 | return; 47 | } 48 | 49 | // relate > 0 = early message 50 | if (relate > m_windowSize) 51 | { 52 | // too early message! 53 | m_peer.LogDebug("Received " + message + " TOO EARLY! Expected " + m_windowStart); 54 | return; 55 | } 56 | 57 | // ok 58 | m_windowStart = (m_windowStart + relate) % NetConstants.NumSequenceNumbers; 59 | m_peer.ReleaseMessage(message); 60 | return; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Lidgren.Network/NetSendResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | /// 6 | /// Result of a SendMessage call 7 | /// 8 | public enum NetSendResult 9 | { 10 | /// 11 | /// Message failed to enqueue because there is no connection 12 | /// 13 | FailedNotConnected = 0, 14 | 15 | /// 16 | /// Message was immediately sent 17 | /// 18 | Sent = 1, 19 | 20 | /// 21 | /// Message was queued for delivery 22 | /// 23 | Queued = 2, 24 | 25 | /// 26 | /// Message was dropped immediately since too many message were queued 27 | /// 28 | Dropped = 3 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Lidgren.Network/NetSenderChannelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | internal abstract class NetSenderChannelBase 6 | { 7 | // access this directly to queue things in this channel 8 | internal NetQueue m_queuedSends; 9 | 10 | internal abstract int WindowSize { get; } 11 | 12 | internal abstract int GetAllowedSends(); 13 | 14 | internal abstract NetSendResult Enqueue(NetOutgoingMessage message); 15 | internal abstract void SendQueuedMessages(float now); 16 | internal abstract void Reset(); 17 | internal abstract void ReceiveAcknowledge(float now, int sequenceNumber); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Lidgren.Network/NetServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Lidgren.Network 5 | { 6 | /// 7 | /// Specialized version of NetPeer used for "server" peers 8 | /// 9 | public class NetServer : NetPeer 10 | { 11 | /// 12 | /// NetServer constructor 13 | /// 14 | public NetServer(NetPeerConfiguration config) 15 | : base(config) 16 | { 17 | config.AcceptIncomingConnections = true; 18 | } 19 | 20 | /// 21 | /// Send a message to all connections 22 | /// 23 | /// The message to send 24 | /// How to deliver the message 25 | public void SendToAll(NetOutgoingMessage msg, NetDeliveryMethod method) 26 | { 27 | var all = this.Connections; 28 | if (all.Count <= 0) 29 | return; 30 | 31 | SendMessage(msg, all, method, 0); 32 | } 33 | 34 | /// 35 | /// Send a message to all connections except one 36 | /// 37 | /// The message to send 38 | /// How to deliver the message 39 | /// Don't send to this particular connection 40 | /// Which sequence channel to use for the message 41 | public void SendToAll(NetOutgoingMessage msg, NetConnection except, NetDeliveryMethod method, int sequenceChannel) 42 | { 43 | var all = this.Connections; 44 | if (all.Count <= 0) 45 | return; 46 | 47 | if (except == null) 48 | { 49 | SendMessage(msg, all, method, sequenceChannel); 50 | return; 51 | } 52 | 53 | List recipients = new List(all.Count - 1); 54 | foreach (var conn in all) 55 | if (conn != except) 56 | recipients.Add(conn); 57 | 58 | if (recipients.Count > 0) 59 | SendMessage(msg, recipients, method, sequenceChannel); 60 | } 61 | 62 | /// 63 | /// Returns a string that represents this object 64 | /// 65 | public override string ToString() 66 | { 67 | return "[NetServer " + ConnectionsCount + " connections]"; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Lidgren.Network/NetStoredReliableMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | internal struct NetStoredReliableMessage 6 | { 7 | public int NumSent; 8 | public float LastSent; 9 | public NetOutgoingMessage Message; 10 | public int SequenceNumber; 11 | 12 | public void Reset() 13 | { 14 | NumSent = 0; 15 | LastSent = 0; 16 | Message = null; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Lidgren.Network/NetTuple.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Lidgren.Network 6 | { 7 | // replace with BCL 4.0 Tuple<> when appropriate 8 | internal struct NetTuple 9 | { 10 | public A Item1; 11 | public B Item2; 12 | 13 | public NetTuple(A item1, B item2) 14 | { 15 | Item1 = item1; 16 | Item2 = item2; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Lidgren.Network/NetUnreliableSequencedReceiver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | internal sealed class NetUnreliableSequencedReceiver : NetReceiverChannelBase 6 | { 7 | private int m_lastReceivedSequenceNumber; 8 | 9 | public NetUnreliableSequencedReceiver(NetConnection connection) 10 | : base(connection) 11 | { 12 | } 13 | 14 | internal override void ReceiveMessage(NetIncomingMessage msg) 15 | { 16 | int nr = msg.m_sequenceNumber; 17 | 18 | // ack no matter what 19 | m_connection.QueueAck(msg.m_receivedMessageType, nr); 20 | 21 | int relate = NetUtility.RelativeSequenceNumber(nr, m_lastReceivedSequenceNumber); 22 | if (relate < 0) 23 | return; // drop if late 24 | 25 | m_lastReceivedSequenceNumber = nr; 26 | m_peer.ReleaseMessage(msg); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Lidgren.Network/NetUnreliableUnorderedReceiver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | internal sealed class NetUnreliableUnorderedReceiver : NetReceiverChannelBase 6 | { 7 | public NetUnreliableUnorderedReceiver(NetConnection connection) 8 | : base(connection) 9 | { 10 | } 11 | 12 | internal override void ReceiveMessage(NetIncomingMessage msg) 13 | { 14 | // ack no matter what 15 | m_connection.QueueAck(msg.m_receivedMessageType, msg.m_sequenceNumber); 16 | 17 | m_peer.ReleaseMessage(msg); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Lidgren.Network/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Lidgren.Network")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Lidgren.Network")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("78f2a988-46e1-4fc4-b7b4-dd2cbe46da6a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("2014.1.7.1")] 36 | [assembly: AssemblyFileVersion("2014.1.7.1")] 37 | [assembly: CLSCompliant(true)] -------------------------------------------------------------------------------- /Lidgren.Network/SenderChannelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lidgren.Network 4 | { 5 | internal abstract class SenderChannelBase 6 | { 7 | internal abstract NetSendResult Send(float now, NetOutgoingMessage message); 8 | internal abstract void SendQueuedMessages(float now); 9 | internal abstract void Reset(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TCPChat 2 | ======= 3 | 4 | ![alt tag](https://raw.github.com/Nirklav/TCPChat/master/screen.png) 5 | 6 | # Description: 7 | Multi-user chat with mixed architecture: client-server, p2p. 8 | Server works tightly with certificates. Server and users should have certificates. But program can generate self signed certificates that supports too, but with some peculiarities. 9 | 10 | First of all if server has self-signed certificate then users those connect to him will be warned. 11 | Users also can use self-signed certificates, if them have it, then them will be marked with the appropriate icons in users list. 12 | Also user can save certificates to local trusted TCPChat storage. 13 | 14 | Here is this user icons: 15 | 16 | 1. ![alt tag](https://raw.github.com/Nirklav/TCPChat/master/UI/Images/checked.png) This is approved certificate. This certificate is valid or it was saved in local TCPChat trusted certificates storage. Also user nick match to certificate common name. 17 | 2. ![alt tag](https://raw.github.com/Nirklav/TCPChat/master/UI/Images/checkedNotMatch.png) This is also approved certificate, but nick does't match to certificate common name. 18 | 3. ![alt tag](https://raw.github.com/Nirklav/TCPChat/master/UI/Images/notChecked.png) This is not approved self-signed certificate. 19 | 20 | # Main idea: 21 | Main idea of this project - is multiple servers without databases. Where you can find friends and recognize that this is really them with he help of certificates. 22 | 23 | # Supports: 24 | 1. Full trafic encryption. Key exchange with certificates. AES-256 CBC. 25 | 2. Private messages. (P2P) 26 | 3. Rooms. 27 | 4. Voice chat. (P2P) 28 | 5. Files sharing. (P2P) 29 | 6. Plugins (Example of simple plugin: https://github.com/Nirklav/ScreenshotPlugin). 30 | 31 | P2P means that connection is established directly between clients without server. 32 | 33 | OpenAL required for audio services. You can download it from [official site](https://www.openal.org/downloads/). 34 | -------------------------------------------------------------------------------- /ServerCertificate.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aoaydin/TCPChat/245d8caadd3dc7884bae06afc00b03fa81905e73/ServerCertificate.cer -------------------------------------------------------------------------------- /UI/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /UI/App.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UI/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Engine.Helpers; 2 | using System; 3 | using System.Windows; 4 | using UI.Infrastructure; 5 | using UI.View; 6 | using UI.ViewModel; 7 | 8 | namespace UI 9 | { 10 | public partial class App : Application 11 | { 12 | protected override void OnStartup(StartupEventArgs e) 13 | { 14 | base.OnStartup(e); 15 | 16 | // Logger 17 | AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; 18 | 19 | // Set localization 20 | Localizer.Instance.Set(Settings.Current.Locale); 21 | 22 | // Create window 23 | var window = new MainWindow(); 24 | var viewModel = new MainViewModel(window); 25 | window.DataContext = viewModel; 26 | window.Show(); 27 | } 28 | 29 | private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) 30 | { 31 | var error = e.ExceptionObject as Exception; 32 | if (error == null) 33 | return; 34 | 35 | var logger = new Logger(AppDomain.CurrentDomain.BaseDirectory + "/UnhandledError.log"); 36 | logger.Write(error); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /UI/Dialogs/AboutProgramDialog.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |