├── .gitignore
├── GladNet.sln
├── LICENSE
├── MyGet.bat
├── README.md
├── clear-bin.bat
├── lib
└── Unity2017
│ └── UnityEngine.dll
├── post-MyGet.ps1
├── src
├── GladNet.API.AutoFac
│ ├── GladNet.API.AutoFac.csproj
│ └── Modules
│ │ ├── AssemblyMessageHandlerServiceModule.cs
│ │ ├── Dispatching
│ │ └── InPlaceMessageDispatchingServiceModule.cs
│ │ ├── GameMessageHandlerServiceModule.cs
│ │ └── GameMessagingServicesModule.cs
├── GladNet.API.Client
│ ├── GladNet.API.Client.csproj
│ └── Session
│ │ └── SessionStarter.cs
├── GladNet.API.Server
│ ├── Application
│ │ ├── GladNetServerApplication.cs
│ │ └── IServerApplicationBase.cs
│ ├── Events
│ │ └── ManagedSessionContextualEventArgs.cs
│ └── GladNet.API.Server.csproj
├── GladNet.API.TCP
│ ├── GladNet.API.TCP.csproj
│ ├── Message
│ │ └── SocketConnectionNetworkMessageInterface.cs
│ ├── Network
│ │ └── SocketConnectionConnectionServiceAdapter.cs
│ └── Session
│ │ ├── BaseTcpManagedSession.cs
│ │ └── SessionCreationContext.cs
├── GladNet.API.WebSocket.DotNetWebSocket
│ ├── Connection
│ │ └── DotNetWebSocketConnection.cs
│ └── GladNet.API.WebSocket.DotNetWebSocket.csproj
├── GladNet.API.WebSocket.UnityWebGL
│ ├── Connection
│ │ ├── IUnityWebGLWebSocket.cs
│ │ ├── UnityWebGLWebSocketFactory.cs
│ │ ├── WebGLMessageSendService.cs
│ │ └── WebGLWebSocketConnection.cs
│ ├── Events
│ │ ├── WebSocketCloseEventHandler.cs
│ │ ├── WebSocketErrorEventHandler.cs
│ │ ├── WebSocketMessageEventHandler.cs
│ │ └── WebSocketOpenEventHandler.cs
│ ├── Extensions
│ │ └── UnityWebGLWebSocketHelpers.cs
│ └── GladNet.API.WebSocket.UnityWebGL.csproj
├── GladNet.API.WebSocket
│ ├── Connection
│ │ └── IWebSocketConnection.cs
│ ├── GladNet.API.WebSocket.csproj
│ ├── Message
│ │ └── WebSocketConnectionNetworkMessageInterface.cs
│ ├── Network
│ │ └── WebSocketConnectionConnectionServiceAdapter.cs
│ └── Session
│ │ ├── BaseClientWebSocketManagedSession.cs
│ │ └── SessionCreationContext.cs
├── GladNet.API
│ ├── Collections
│ │ ├── AsyncExProducerConsumerQueueAsyncMessageQueue.cs
│ │ └── IAsyncMessageQueue.cs
│ ├── Constants
│ │ └── NetworkConnectionOptionsConstants.cs
│ ├── Extensions
│ │ ├── IDisposableAttachableExtensions.cs
│ │ └── IMessageSendServiceExtensions.cs
│ ├── GladNet.API.csproj
│ ├── Message
│ │ ├── Dispatching
│ │ │ ├── INetworkMessageDispatchingStrategy.cs
│ │ │ └── InPlaceNetworkMessageDispatchingStrategy.cs
│ │ ├── Header
│ │ │ ├── HeaderlessPacketHeader.cs
│ │ │ ├── IPacketHeader.cs
│ │ │ ├── IPacketHeaderFactory.cs
│ │ │ ├── PacketHeaderCreationContext.cs
│ │ │ └── PacketHeaderSerializationContext.cs
│ │ ├── INetworkOutgoingMessage.cs
│ │ ├── IPeerMessageContext.cs
│ │ ├── IPeerSessionMessageContext.cs
│ │ ├── NetworkIncomingMessage.cs
│ │ ├── SendResult.cs
│ │ ├── Serialization
│ │ │ ├── IMessageDeserializer.cs
│ │ │ └── IMessageSerializer.cs
│ │ ├── Services
│ │ │ ├── IMessageSendService.cs
│ │ │ ├── INetworkMessageInterface.cs
│ │ │ ├── INetworkMessageReceivable.cs
│ │ │ └── QueueBasedMessageSendService.cs
│ │ └── SessionMessageContext.cs
│ ├── Network
│ │ ├── INetworkConnectable.cs
│ │ ├── INetworkDisconnectable.cs
│ │ ├── NetworkAddressInfo.cs
│ │ └── NetworkConnectionOptions.cs
│ ├── Service
│ │ └── INetworkConnectionService.cs
│ └── Session
│ │ ├── IManagedSession.cs
│ │ ├── ManagedSession.cs
│ │ ├── ManagedSessionGeneric.cs
│ │ ├── ServiceContainers
│ │ ├── SessionMessageBuildingServiceContext.cs
│ │ └── SessionMessageInterfaceServiceContext.cs
│ │ └── SessionDetails.cs
├── GladNet.Client.DotNetTcpClient
│ ├── GladNet.Client.DotNetTcpClient.csproj
│ ├── Memory
│ │ └── GladNetPipeMemoryPool.cs
│ └── TCPSocketConnectionFactory.cs
├── GladNet.Server.DotNetTcpServer
│ ├── GladNet.Server.DotNetTcpServer.csproj
│ └── TcpGladNetServerApplication.cs
└── GladNet.Server.DotNetWebSocketServer
│ ├── GladNet.Server.DotNetWebSocketServer.csproj
│ └── WebSocketGladNetServerApplication.cs
└── tests
├── GladNet.DotNetTcpClient.EchoTest
├── ConsoleLogger.cs
├── GladNet.DotNetTcpClient.EchoTest.csproj
├── Network
│ ├── Handlers
│ │ └── DefaultStringMessageHandler.cs
│ ├── Session
│ │ ├── StringMessagePacketHeaderFactory.cs
│ │ ├── StringMessageSerializer.cs
│ │ └── StringPacketHeaderSerializer.cs
│ └── TCPEchoClientSession.cs
└── Program.cs
├── GladNet.DotNetTcpServer.EchoTest
├── ConsoleLogger.cs
├── GladNet.DotNetTcpServer.EchoTest.csproj
├── Network
│ ├── Handlers
│ │ └── DefaultStringMessageHandler.cs
│ ├── Session
│ │ ├── StringMessagePacketHeaderFactory.cs
│ │ ├── StringMessageSerializer.cs
│ │ └── StringPacketHeaderSerializer.cs
│ ├── TCPEchoGladNetServerApplication.cs
│ └── TCPEchoManagedSession.cs
└── Program.cs
└── GladNet.WebSocket.EchoTest
├── GladNet.WebSocket.EchoTest.csproj
└── Program.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | push-nuget.ps1
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | build/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]ib/Dependency Builds/
27 |
28 | # Visual Studo 2015 cache/options directory
29 | .vs/
30 |
31 | # MSTest test Results
32 | [Tt]est[Rr]esult*/
33 | [Bb]uild[Ll]og.*
34 |
35 | # NUNIT
36 | *.VisualState.xml
37 | TestResult.xml
38 |
39 | # Build Results of an ATL Project
40 | [Dd]ebugPS/
41 | [Rr]eleasePS/
42 | dlldata.c
43 |
44 | *_i.c
45 | *_p.c
46 | *_i.h
47 | *.ilk
48 | *.meta
49 | *.obj
50 | *.pch
51 | *.pdb
52 | *.pgc
53 | *.pgd
54 | *.rsp
55 | *.sbr
56 | *.tlb
57 | *.tli
58 | *.tlh
59 | *.tmp
60 | *.tmp_proj
61 | *.log
62 | *.vspscc
63 | *.vssscc
64 | .builds
65 | *.pidb
66 | *.svclog
67 | *.scc
68 |
69 | # Chutzpah Test files
70 | _Chutzpah*
71 |
72 | # Visual C++ cache files
73 | ipch/
74 | *.aps
75 | *.ncb
76 | *.opensdf
77 | *.sdf
78 | *.cachefile
79 |
80 | # Visual Studio profiler
81 | *.psess
82 | *.vsp
83 | *.vspx
84 |
85 | # TFS 2012 Local Workspace
86 | $tf/
87 |
88 | # Guidance Automation Toolkit
89 | *.gpState
90 |
91 | # ReSharper is a .NET coding add-in
92 | _ReSharper*/
93 | *.[Rr]e[Ss]harper
94 | *.DotSettings.user
95 |
96 | # JustCode is a .NET coding addin-in
97 | .JustCode
98 |
99 | # TeamCity is a build add-in
100 | _TeamCity*
101 |
102 | # DotCover is a Code Coverage Tool
103 | *.dotCover
104 |
105 | # NCrunch
106 | _NCrunch_*
107 | .*crunch*.local.xml
108 | *.ncrunch*
109 | nCrunchTemp_*
110 |
111 | # MightyMoose
112 | *.mm.*
113 | AutoTest.Net/
114 |
115 | # Web workbench (sass)
116 | .sass-cache/
117 |
118 | # Installshield output folder
119 | [Ee]xpress/
120 |
121 | # DocProject is a documentation generator add-in
122 | DocProject/buildhelp/
123 | DocProject/Help/*.HxT
124 | DocProject/Help/*.HxC
125 | DocProject/Help/*.hhc
126 | DocProject/Help/*.hhk
127 | DocProject/Help/*.hhp
128 | DocProject/Help/Html2
129 | DocProject/Help/html
130 |
131 | # Click-Once directory
132 | publish/
133 |
134 | # Publish Web Output
135 | *.[Pp]ublish.xml
136 | *.azurePubxml
137 | # TODO: Comment the next line if you want to checkin your web deploy settings
138 | # but database connection strings (with potential passwords) will be unencrypted
139 | *.pubxml
140 | *.publishproj
141 |
142 | # NuGet Packages
143 | *.nupkg
144 | # The packages folder can be ignored because of Package Restore
145 | **/packages/*
146 | # except build/, which is used as an MSBuild target.
147 | !**/packages/build/
148 | # Uncomment if necessary however generally it will be regenerated when needed
149 | #!**/packages/repositories.config
150 |
151 | # Windows Azure Build Output
152 | csx/
153 | *.build.csdef
154 |
155 | # Windows Store app package directory
156 | AppPackages/
157 |
158 | # Others
159 | *.[Cc]ache
160 | ClientBin/
161 | [Ss]tyle[Cc]op.*
162 | ~$*
163 | *~
164 | *.dbmdl
165 | *.dbproj.schemaview
166 | *.publishsettings
167 | node_modules/
168 | bower_components/
169 |
170 | # RIA/Silverlight projects
171 | Generated_Code/
172 |
173 | # Backup & report files from converting an old project file
174 | # to a newer Visual Studio version. Backup files are not needed,
175 | # because we have git ;-)
176 | _UpgradeReport_Files/
177 | Backup*/
178 | UpgradeLog*.XML
179 | UpgradeLog*.htm
180 |
181 | # SQL Server files
182 | *.mdf
183 | *.ldf
184 |
185 | # Business Intelligence projects
186 | *.rdl.data
187 | *.bim.layout
188 | *.bim_*.settings
189 |
190 | # Microsoft Fakes
191 | FakesAssemblies/
192 |
193 | # Node.js Tools for Visual Studio
194 | .ntvs_analysis.dat
195 |
196 | # Visual Studio 6 build log
197 | *.plg
198 |
199 | # Visual Studio 6 workspace options file
200 | *.opt
201 |
--------------------------------------------------------------------------------
/GladNet.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30804.86
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{82223BC2-FD46-45B7-8714-A1BBB6FACC0E}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API", "src\GladNet.API\GladNet.API.csproj", "{1B6D4F01-C4BB-4242-89F9-F17527BF442E}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API.Server", "src\GladNet.API.Server\GladNet.API.Server.csproj", "{26682A85-BEEC-4D96-A843-0925890E472B}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.Server.DotNetTcpServer", "src\GladNet.Server.DotNetTcpServer\GladNet.Server.DotNetTcpServer.csproj", "{A8243286-3CB8-4B81-8379-A61DEAA39D09}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{EE396D2F-98B0-46DC-851E-8A52A4C46E6B}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.DotNetTcpServer.EchoTest", "tests\GladNet.DotNetTcpServer.EchoTest\GladNet.DotNetTcpServer.EchoTest.csproj", "{E6C56850-6930-4863-88AA-7FAC7592E70B}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API.Client", "src\GladNet.API.Client\GladNet.API.Client.csproj", "{28DB2EDC-FA18-4F55-8AD9-3B5DE543F519}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API.TCP", "src\GladNet.API.TCP\GladNet.API.TCP.csproj", "{E9F23B76-BCCE-41A3-A4AB-CB6FB36C6B5F}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.Client.DotNetTcpClient", "src\GladNet.Client.DotNetTcpClient\GladNet.Client.DotNetTcpClient.csproj", "{BA324EF9-0A69-42CC-B771-3A4200BEC3CE}"
23 | EndProject
24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.DotNetTcpClient.EchoTest", "tests\GladNet.DotNetTcpClient.EchoTest\GladNet.DotNetTcpClient.EchoTest.csproj", "{F349568E-02A0-4B46-9AD6-B78C2DBF5240}"
25 | EndProject
26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API.AutoFac", "src\GladNet.API.AutoFac\GladNet.API.AutoFac.csproj", "{269BD7A7-3E02-4FE5-AC58-79475DB97E7D}"
27 | EndProject
28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API.WebSocket", "src\GladNet.API.WebSocket\GladNet.API.WebSocket.csproj", "{98542DA6-E718-4249-976F-DFAF30537398}"
29 | EndProject
30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.WebSocket.EchoTest", "tests\GladNet.WebSocket.EchoTest\GladNet.WebSocket.EchoTest.csproj", "{4EB331A8-C2C8-4EA4-BFE9-1C5682FA6266}"
31 | EndProject
32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.Server.DotNetWebSocketServer", "src\GladNet.Server.DotNetWebSocketServer\GladNet.Server.DotNetWebSocketServer.csproj", "{94924166-0227-4884-8313-7D528B958AA4}"
33 | EndProject
34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API.WebSocket.DotNetWebSocket", "src\GladNet.API.WebSocket.DotNetWebSocket\GladNet.API.WebSocket.DotNetWebSocket.csproj", "{A329F06E-F71D-4D65-9CBD-C97CA3DEB799}"
35 | EndProject
36 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GladNet.API.WebSocket.UnityWebGL", "src\GladNet.API.WebSocket.UnityWebGL\GladNet.API.WebSocket.UnityWebGL.csproj", "{678A2755-69F1-4EE3-AE39-754D812048FF}"
37 | EndProject
38 | Global
39 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
40 | Debug|Any CPU = Debug|Any CPU
41 | Release|Any CPU = Release|Any CPU
42 | EndGlobalSection
43 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
44 | {1B6D4F01-C4BB-4242-89F9-F17527BF442E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {1B6D4F01-C4BB-4242-89F9-F17527BF442E}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {1B6D4F01-C4BB-4242-89F9-F17527BF442E}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {1B6D4F01-C4BB-4242-89F9-F17527BF442E}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {26682A85-BEEC-4D96-A843-0925890E472B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {26682A85-BEEC-4D96-A843-0925890E472B}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {26682A85-BEEC-4D96-A843-0925890E472B}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {26682A85-BEEC-4D96-A843-0925890E472B}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {A8243286-3CB8-4B81-8379-A61DEAA39D09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {A8243286-3CB8-4B81-8379-A61DEAA39D09}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {A8243286-3CB8-4B81-8379-A61DEAA39D09}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {A8243286-3CB8-4B81-8379-A61DEAA39D09}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {E6C56850-6930-4863-88AA-7FAC7592E70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57 | {E6C56850-6930-4863-88AA-7FAC7592E70B}.Debug|Any CPU.Build.0 = Debug|Any CPU
58 | {E6C56850-6930-4863-88AA-7FAC7592E70B}.Release|Any CPU.ActiveCfg = Release|Any CPU
59 | {E6C56850-6930-4863-88AA-7FAC7592E70B}.Release|Any CPU.Build.0 = Release|Any CPU
60 | {28DB2EDC-FA18-4F55-8AD9-3B5DE543F519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {28DB2EDC-FA18-4F55-8AD9-3B5DE543F519}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {28DB2EDC-FA18-4F55-8AD9-3B5DE543F519}.Release|Any CPU.ActiveCfg = Release|Any CPU
63 | {28DB2EDC-FA18-4F55-8AD9-3B5DE543F519}.Release|Any CPU.Build.0 = Release|Any CPU
64 | {E9F23B76-BCCE-41A3-A4AB-CB6FB36C6B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
65 | {E9F23B76-BCCE-41A3-A4AB-CB6FB36C6B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
66 | {E9F23B76-BCCE-41A3-A4AB-CB6FB36C6B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
67 | {E9F23B76-BCCE-41A3-A4AB-CB6FB36C6B5F}.Release|Any CPU.Build.0 = Release|Any CPU
68 | {BA324EF9-0A69-42CC-B771-3A4200BEC3CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69 | {BA324EF9-0A69-42CC-B771-3A4200BEC3CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
70 | {BA324EF9-0A69-42CC-B771-3A4200BEC3CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
71 | {BA324EF9-0A69-42CC-B771-3A4200BEC3CE}.Release|Any CPU.Build.0 = Release|Any CPU
72 | {F349568E-02A0-4B46-9AD6-B78C2DBF5240}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
73 | {F349568E-02A0-4B46-9AD6-B78C2DBF5240}.Debug|Any CPU.Build.0 = Debug|Any CPU
74 | {F349568E-02A0-4B46-9AD6-B78C2DBF5240}.Release|Any CPU.ActiveCfg = Release|Any CPU
75 | {F349568E-02A0-4B46-9AD6-B78C2DBF5240}.Release|Any CPU.Build.0 = Release|Any CPU
76 | {269BD7A7-3E02-4FE5-AC58-79475DB97E7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
77 | {269BD7A7-3E02-4FE5-AC58-79475DB97E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
78 | {269BD7A7-3E02-4FE5-AC58-79475DB97E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
79 | {269BD7A7-3E02-4FE5-AC58-79475DB97E7D}.Release|Any CPU.Build.0 = Release|Any CPU
80 | {98542DA6-E718-4249-976F-DFAF30537398}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
81 | {98542DA6-E718-4249-976F-DFAF30537398}.Debug|Any CPU.Build.0 = Debug|Any CPU
82 | {98542DA6-E718-4249-976F-DFAF30537398}.Release|Any CPU.ActiveCfg = Release|Any CPU
83 | {98542DA6-E718-4249-976F-DFAF30537398}.Release|Any CPU.Build.0 = Release|Any CPU
84 | {4EB331A8-C2C8-4EA4-BFE9-1C5682FA6266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
85 | {4EB331A8-C2C8-4EA4-BFE9-1C5682FA6266}.Debug|Any CPU.Build.0 = Debug|Any CPU
86 | {4EB331A8-C2C8-4EA4-BFE9-1C5682FA6266}.Release|Any CPU.ActiveCfg = Release|Any CPU
87 | {4EB331A8-C2C8-4EA4-BFE9-1C5682FA6266}.Release|Any CPU.Build.0 = Release|Any CPU
88 | {94924166-0227-4884-8313-7D528B958AA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
89 | {94924166-0227-4884-8313-7D528B958AA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
90 | {94924166-0227-4884-8313-7D528B958AA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
91 | {94924166-0227-4884-8313-7D528B958AA4}.Release|Any CPU.Build.0 = Release|Any CPU
92 | {A329F06E-F71D-4D65-9CBD-C97CA3DEB799}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
93 | {A329F06E-F71D-4D65-9CBD-C97CA3DEB799}.Debug|Any CPU.Build.0 = Debug|Any CPU
94 | {A329F06E-F71D-4D65-9CBD-C97CA3DEB799}.Release|Any CPU.ActiveCfg = Release|Any CPU
95 | {A329F06E-F71D-4D65-9CBD-C97CA3DEB799}.Release|Any CPU.Build.0 = Release|Any CPU
96 | {678A2755-69F1-4EE3-AE39-754D812048FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
97 | {678A2755-69F1-4EE3-AE39-754D812048FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
98 | {678A2755-69F1-4EE3-AE39-754D812048FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
99 | {678A2755-69F1-4EE3-AE39-754D812048FF}.Release|Any CPU.Build.0 = Release|Any CPU
100 | EndGlobalSection
101 | GlobalSection(SolutionProperties) = preSolution
102 | HideSolutionNode = FALSE
103 | EndGlobalSection
104 | GlobalSection(NestedProjects) = preSolution
105 | {1B6D4F01-C4BB-4242-89F9-F17527BF442E} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
106 | {26682A85-BEEC-4D96-A843-0925890E472B} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
107 | {A8243286-3CB8-4B81-8379-A61DEAA39D09} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
108 | {E6C56850-6930-4863-88AA-7FAC7592E70B} = {EE396D2F-98B0-46DC-851E-8A52A4C46E6B}
109 | {28DB2EDC-FA18-4F55-8AD9-3B5DE543F519} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
110 | {E9F23B76-BCCE-41A3-A4AB-CB6FB36C6B5F} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
111 | {BA324EF9-0A69-42CC-B771-3A4200BEC3CE} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
112 | {F349568E-02A0-4B46-9AD6-B78C2DBF5240} = {EE396D2F-98B0-46DC-851E-8A52A4C46E6B}
113 | {269BD7A7-3E02-4FE5-AC58-79475DB97E7D} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
114 | {98542DA6-E718-4249-976F-DFAF30537398} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
115 | {4EB331A8-C2C8-4EA4-BFE9-1C5682FA6266} = {EE396D2F-98B0-46DC-851E-8A52A4C46E6B}
116 | {94924166-0227-4884-8313-7D528B958AA4} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
117 | {A329F06E-F71D-4D65-9CBD-C97CA3DEB799} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
118 | {678A2755-69F1-4EE3-AE39-754D812048FF} = {82223BC2-FD46-45B7-8714-A1BBB6FACC0E}
119 | EndGlobalSection
120 | GlobalSection(ExtensibilityGlobals) = postSolution
121 | SolutionGuid = {886DD3D7-35E3-42F0-8CE9-74FB5AD7BBD0}
122 | EndGlobalSection
123 | EndGlobal
124 |
--------------------------------------------------------------------------------
/MyGet.bat:
--------------------------------------------------------------------------------
1 | nuget restore GladNet.sln
2 | dotnet restore GladNet.sln
3 | dotnet build GladNet.sln -c Release
4 | PAUSE
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GladNet (Glader's Library of Advanced Development for Network Emulation Technologies)
2 |
3 | Introducing GladNet4, the 4th generation of the .NET/C# GladNet networking library.
4 | Originally designed for the niche of server/client network game emulation, GladNet has evolved into a generalized C#/.NET networking library, with a continued focus on games networking. GladNet4 offers a collection of APIs that enable developers to quickly build client or server software in .NET/C#. The library features an extendable API, supporting multiple cryptography schemes and serializers, making it highly adaptable.
5 |
6 | ## Features
7 |
8 | **Client**
9 | - [x] Async
10 | - [x] TCP
11 | - [x] Websockets
12 | - [x] [FreecraftCore.Serializer](https://www.github.com/FreecraftCore) (Attribute-based custom binary protocol serializer)
13 | - [ ] JSON
14 | - [x] Protobuf
15 | - [ ] XML
16 |
17 | **Server**
18 |
19 | - [x] Async
20 | - [x] TCP
21 | - [x] Websockets
22 |
23 | ## License
24 |
25 | Contributions including pull requests, commits, notes, dumps, gists or anything else in the repository are licensed under the below licensing terms.
26 |
27 | AGPL with the exception that an unrestricted perpetual non-exclusive license is granted to [HelloKitty](https://www.github.com/HelloKitty) (Andrew Blakely)
28 |
--------------------------------------------------------------------------------
/clear-bin.bat:
--------------------------------------------------------------------------------
1 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S bin') DO RMDIR /S /Q "%%G"
2 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S publish') DO RMDIR /S /Q "%%G"
--------------------------------------------------------------------------------
/lib/Unity2017/UnityEngine.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloKitty/GladNet/8b00743190458228c9124430bf63cf872be26670/lib/Unity2017/UnityEngine.dll
--------------------------------------------------------------------------------
/post-MyGet.ps1:
--------------------------------------------------------------------------------
1 | ##Looks through the entire src directory and runs nuget pack with dependencies added on each csproj found
2 | ##foreach file in src/*
3 | foreach($f in Get-ChildItem ./src/)
4 | {
5 | ##foreach file in the src/*/ directory that ends with the .csproj format
6 | foreach($ff in (Get-ChildItem (Join-Path ./src/ $f.Name) | Where-Object { $_.Name.EndsWith(".csproj") }))
7 | {
8 | ##Add the project path + the csproj name and add the include referenced projects argument which will
9 | ##force nuget dependencies
10 | $projectArgs = "pack " + (Join-Path (Join-Path src/ $f.Name) $ff.Name)##
11 | $projectArgs = $projectArgs + " -c Release --include-symbols -p:PackageVersion=3.0.48"
12 | Start-Process dotnet $projectArgs -Wait
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/GladNet.API.AutoFac/GladNet.API.AutoFac.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 | Andrew Blakely, HelloKitty
6 |
7 | GladNet
8 | GladNet (Glader's Library for Advanced Development of Network Emulation Technologies) server API library.
9 | Andrew Blakely
10 | https://github.com/HelloKitty/GladNet3/blob/master/LICENSE
11 | https://github.com/HelloKitty/GladNet3
12 | https://github.com/HelloKitty/GladNet3
13 | git
14 | GladNet Emulation Emulator WoW PSO Network Unity3D Network Networking Netlib GladNet4
15 | GladNet.API.AutoFac
16 | 4.9.45
17 |
18 |
19 |
20 | true
21 | true
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/GladNet.API.AutoFac/Modules/AssemblyMessageHandlerServiceModule.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using Autofac;
7 | using Glader.Essentials;
8 | using Module = Autofac.Module;
9 |
10 | namespace GladNet
11 | {
12 | ///
13 | /// Service module that registers all message handlers within the provided
14 | ///
15 | public class AssemblyMessageHandlerServiceModule : Module where TMessageReadType : class where TMessageWriteType : class
16 | {
17 | private Assembly TargetAssembly { get; }
18 |
19 | public AssemblyMessageHandlerServiceModule(Assembly targetAssembly)
20 | {
21 | TargetAssembly = targetAssembly ?? throw new ArgumentNullException(nameof(targetAssembly));
22 | }
23 |
24 | protected override void Load(ContainerBuilder builder)
25 | {
26 | base.Load(builder);
27 |
28 | //Register all handlers in the assembly
29 | foreach(var handler in GetHandlerTypes(TargetAssembly))
30 | RegisterHandler(builder, handler);
31 | }
32 |
33 | ///
34 | /// Registers a bindable in the provider container.
35 | ///
36 | /// The handler to register.
37 | ///
38 | ///
39 | private ContainerBuilder RegisterHandler(ContainerBuilder builder)
40 | where THandlerType : IMessageHandler>,
41 | ITypeBindable>, TMessageReadType>
42 | {
43 | RegisterHandler(builder, typeof(THandlerType));
44 | return builder;
45 | }
46 |
47 | ///
48 | /// Registers a bindable in the provider container.
49 | ///
50 | ///
51 | /// Type of handler.
52 | /// Throws if the handler type isn't a message handler.
53 | ///
54 | private static void RegisterHandler(ContainerBuilder builder, Type handlerType)
55 | {
56 | //New design will give a unique handler per session.
57 | //Makes this SO much easier in some cases.
58 | var registrationBuilder = builder.RegisterType(handlerType)
59 | .As>, TMessageReadType>>()
60 | .InstancePerLifetimeScope();
61 |
62 | //TODO: Assert it is assignable to.
63 | foreach(var additional in handlerType.GetCustomAttributes())
64 | registrationBuilder = registrationBuilder
65 | .As(additional.ServiceType);
66 | }
67 |
68 | ///
69 | /// Parses the provided to locate all handler types.
70 | ///
71 | /// The assembly to parse.
72 | /// Enumerable of all available message handler types.
73 | private static IEnumerable GetHandlerTypes(Assembly assembly)
74 | {
75 | if(assembly == null) throw new ArgumentNullException(nameof(assembly));
76 |
77 | return assembly.GetTypes()
78 | .Where(t => t.IsAssignableTo>, TMessageReadType>>())
79 | .Where(t => !t.IsAbstract)
80 | .Where(t => !t.IsAssignableTo>>()) //not a default handler
81 | .ToArray();
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/GladNet.API.AutoFac/Modules/Dispatching/InPlaceMessageDispatchingServiceModule.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Autofac;
5 |
6 | namespace GladNet
7 | {
8 | //From Booma
9 | ///
10 | /// Service registration module for .
11 | /// Registers for in-place message dispatching.
12 | ///
13 | ///
14 | ///
15 | public sealed class InPlaceMessageDispatchingServiceModule : Module
16 | where TMessageWriteType : class
17 | where TMessageReadType : class
18 | {
19 | protected override void Load(ContainerBuilder builder)
20 | {
21 | base.Load(builder);
22 |
23 | //Register just inplace dispatching which is basically handle on same thread.
24 | builder.RegisterType>()
25 | .AsImplementedInterfaces()
26 | .InstancePerLifetimeScope();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/GladNet.API.AutoFac/Modules/GameMessageHandlerServiceModule.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using Autofac;
7 | using Glader.Essentials;
8 | using GladNet;
9 | using Module = Autofac.Module;
10 |
11 | namespace GladNet
12 | {
13 | //From Booma
14 | ///
15 | /// Game message handler service module.
16 | /// Registers the services and handling for message handlers.
17 | /// Registers the following services:
18 | /// for
19 | ///
20 | /// for specified message types parameters.
21 | ///
22 | public abstract class GameMessageHandlerServiceModule : Module
23 | where TMessageReadType : class
24 | where TMessageWriteType : class
25 | where TDefaultHandlerType : BaseDefaultMessageHandler>
26 | {
27 | ///
28 | protected sealed override void Load(ContainerBuilder builder)
29 | {
30 | base.Load(builder);
31 |
32 | //We Register the default handler because we'll internally bind it to the handler service
33 | //we create. This simplifies handler discovery abit too.
34 | builder.RegisterType()
35 | .AsSelf()
36 | .As>>()
37 | .SingleInstance();
38 |
39 | //New Design makes these handlers NOT stateless. It makes certain things WAY easier to deal with.
40 | builder
41 | .RegisterType>>()
42 | .As>>()
43 | .OnActivated(args =>
44 | {
45 | //Bind one of the default handlers
46 | var handler = args.Context.Resolve();
47 | args.Instance.Bind(handler);
48 |
49 | //Now we resolve ALL bindable handlers
50 | //Any handler that is registered will now be bound to this handler service.
51 | foreach (var bindable in args.Context.Resolve>, TMessageReadType>>>())
52 | {
53 | bindable.BindTo(args.Instance);
54 | }
55 | })
56 | .InstancePerLifetimeScope();
57 |
58 | RegisterHandlers(builder);
59 | }
60 |
61 | ///
62 | /// Implementers can register additional handlers here.
63 | ///
64 | ///
65 | protected virtual void RegisterHandlers(ContainerBuilder builder)
66 | {
67 |
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/GladNet.API.AutoFac/Modules/GameMessagingServicesModule.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Autofac;
5 |
6 | namespace GladNet
7 | {
8 | ///
9 | /// Service module that registers the following services:
10 | ///
11 | /// for outgoing write types
12 | /// .
13 | ///
14 | ///
15 | ///
16 | public sealed class GameMessagingServicesModule : Module
17 | where TMessageWriteType : class
18 | where TMessageReadType : class
19 | {
20 | protected override void Load(ContainerBuilder builder)
21 | {
22 | base.Load(builder);
23 |
24 | //The following registers messaging and message interface dependencies.
25 | builder.RegisterType>()
26 | .As>()
27 | .InstancePerLifetimeScope();
28 |
29 | builder.RegisterType>()
30 | .As>()
31 | .InstancePerLifetimeScope();
32 |
33 | builder.RegisterType>()
34 | .AsSelf()
35 | .InstancePerLifetimeScope();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/GladNet.API.Client/GladNet.API.Client.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 | Andrew Blakely, HelloKitty
6 |
7 | GladNet
8 | GladNet (Glader's Library for Advanced Development of Network Emulation Technologies) server API library.
9 | Andrew Blakely
10 | https://github.com/HelloKitty/GladNet3/blob/master/LICENSE
11 | https://github.com/HelloKitty/GladNet3
12 | https://github.com/HelloKitty/GladNet3
13 | git
14 | GladNet Emulation Emulator WoW PSO Network Unity3D Network Networking Netlib GladNet4
15 | GladNet.API.Client
16 | 4.9.45
17 |
18 |
19 |
20 | true
21 | true
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/GladNet.API.Client/Session/SessionStarter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Common.Logging;
7 |
8 | namespace GladNet
9 | {
10 | //TODO: This is unfinished, not generalized enough to use in Server side yet.
11 | public sealed class SessionStarter
12 | where TSessionType : ManagedSession, IDisposable
13 | {
14 | private ILog Logger { get; }
15 |
16 | public SessionStarter(ILog logger)
17 | {
18 | Logger = logger ?? throw new ArgumentNullException(nameof(logger));
19 | }
20 |
21 | public async Task StartAsync(TSessionType session, CancellationToken token = default)
22 | {
23 | Task writeTask = Task.Run(async () => await StartSessionNetworkThreadAsync(session.Details, session.StartWritingAsync(token), "Write"), token);
24 | Task readTask = Task.Run(async () => await StartSessionNetworkThreadAsync(session.Details, session.StartListeningAsync(token), "Read"), token);
25 |
26 | await Task.Run(async () =>
27 | {
28 | try
29 | {
30 | await Task.WhenAny(writeTask, readTask);
31 | }
32 | catch(Exception e)
33 | {
34 | //Suppress this exception, we have critical deconstruction code to run.
35 | if(Logger.IsErrorEnabled)
36 | Logger.Error($"Session: {session.Details.ConnectionId} encountered critical failure in awaiting network task. Error: {e}");
37 | }
38 | finally
39 | {
40 | if(Logger.IsDebugEnabled)
41 | Logger.Debug($"Session Stopping. Read State Error: {readTask.IsFaulted} Write State Error: {writeTask.IsFaulted} Read Completed: {readTask.IsCompleted} Write Completed: {writeTask.IsCompleted} Read Cancelled: {readTask.IsCanceled} Write Cancelled: {writeTask.IsCanceled}");
42 |
43 | if (readTask.IsFaulted)
44 | if(Logger.IsDebugEnabled)
45 | Logger.Debug($"Read Fault: {readTask.Exception}");
46 |
47 | if(writeTask.IsFaulted)
48 | if(Logger.IsDebugEnabled)
49 | Logger.Debug($"Write Fault: {readTask.Exception}");
50 |
51 | await TryGracefulDisconnectAsync(session);
52 | }
53 |
54 | if (Logger.IsDebugEnabled)
55 | Logger.Debug($"Session: {session.Details.ConnectionId} Stopped Network Read/Write.");
56 |
57 | try
58 | {
59 | //TODO: Maybe a general disconnection event???
60 | }
61 | catch(Exception e)
62 | {
63 | if(Logger.IsErrorEnabled)
64 | Logger.Error($"Failed Session: {session.Details.ConnectionId} ended event. Reason: {e}");
65 | }
66 | finally
67 | {
68 | try
69 | {
70 | session.Dispose();
71 | }
72 | catch(Exception e)
73 | {
74 | if(Logger.IsErrorEnabled)
75 | Logger.Error($"Encountered error in Client: {session.Details.ConnectionId} session disposal. Error: {e}");
76 | throw;
77 | }
78 | }
79 | }, token);
80 | }
81 |
82 | private async Task TryGracefulDisconnectAsync(TSessionType session)
83 | {
84 | try
85 | {
86 | await session.ConnectionService.DisconnectAsync();
87 | }
88 | catch (Exception e)
89 | {
90 | if (Logger.IsErrorEnabled)
91 | Logger.Error($"Session: {session.Details.ConnectionId} was open but failed to disconnect. Reason: {e}");
92 | }
93 | finally
94 | {
95 | try
96 | {
97 | session.Dispose();
98 | }
99 | catch (Exception e)
100 | {
101 | if (Logger.IsErrorEnabled)
102 | Logger.Error($"Session: {session.Details.ConnectionId} failed to dispose. Reason: {e}");
103 | }
104 | }
105 | }
106 |
107 | public void Start(TSessionType session, CancellationToken token = default)
108 | {
109 | //Don't block/await (fire and forget)
110 | #pragma warning disable 4014
111 | StartAsync(session, token);
112 | #pragma warning restore 4014
113 | }
114 |
115 | private async Task StartSessionNetworkThreadAsync(SessionDetails details, Task task, string taskName)
116 | {
117 | if(details == null) throw new ArgumentNullException(nameof(details));
118 | if(task == null) throw new ArgumentNullException(nameof(task));
119 |
120 | try
121 | {
122 | await task;
123 | }
124 | catch(Exception e)
125 | {
126 | if(Logger.IsErrorEnabled)
127 | Logger.Error($"Session: {details.ConnectionId} encountered error in network {taskName} thread. Error: {e}");
128 | }
129 | finally
130 | {
131 |
132 | }
133 | }
134 |
135 | public void Dispose()
136 | {
137 | // WARNING: heed warning in Thread.Abort doc, don't do it
138 | // See: https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=net-8.0
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/GladNet.API.Server/Application/GladNetServerApplication.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Common.Logging;
8 | using Glader.Essentials;
9 |
10 | namespace GladNet
11 | {
12 | ///
13 | /// Base type for GladNet server application bases.
14 | ///
15 | ///
16 | ///
17 | public abstract class GladNetServerApplication
18 | : IServerApplicationListenable, IFactoryCreatable
19 | where TManagedSessionType : ManagedSession
20 | {
21 | ///
22 | /// Network address information for the server.
23 | ///
24 | public NetworkAddressInfo ServerAddress { get; }
25 |
26 | ///
27 | /// Server application logger.
28 | ///
29 | public ILog Logger { get; }
30 |
31 | //TODO: We need a better API for exposing this.
32 | ///
33 | /// Collection that maps connection id to the managed session types.
34 | ///
35 | protected ConcurrentDictionary Sessions { get; } = new ConcurrentDictionary();
36 |
37 | ///
38 | /// Event that is fired when a managed session is ended.
39 | /// This could be caused by disconnection but is not required to be related to disconnection.
40 | ///
41 | public event EventHandler> OnManagedSessionEnded;
42 |
43 | ///
44 | /// Creates a new server application with the specified address.
45 | ///
46 | /// Address for listening.
47 | /// The logger.
48 | protected GladNetServerApplication(NetworkAddressInfo serverAddress, ILog logger)
49 | {
50 | ServerAddress = serverAddress ?? throw new ArgumentNullException(nameof(serverAddress));
51 | Logger = logger ?? throw new ArgumentNullException(nameof(logger));
52 | }
53 |
54 | ///
55 | public abstract Task BeginListeningAsync(CancellationToken token = default);
56 |
57 | //Should be overriden by the consumer of the library.
58 | ///
59 | /// Called internally when a session is being created.
60 | /// This method should produce a valid session and is considered the hub of the connection.
61 | ///
62 | /// The context for creating the managed session.
63 | /// A non-null session.
64 | public abstract TManagedSessionType Create(TSessionCreationContextType context);
65 |
66 | ///
67 | /// Starts the read/write network tasks.
68 | ///
69 | /// The network cancel tokens.
70 | /// The session.
71 | protected void StartNetworkSessionTasks(CancellationToken token, TManagedSessionType clientSession)
72 | {
73 | Task writeTask = Task.Run(async () =>
74 | {
75 | try
76 | {
77 | await StartSessionNetworkThreadAsync(clientSession.Details, clientSession.StartWritingAsync(token), token, "Write");
78 | }
79 | catch (Exception e)
80 | {
81 | if(Logger.IsErrorEnabled)
82 | Logger.Error($"Session: {clientSession.Details.ConnectionId} Write thread encountered critical failure. Error: {e}");
83 | throw;
84 | }
85 | }, token);
86 |
87 | Task readTask = Task.Run(async () =>
88 | {
89 | try
90 | {
91 | await StartSessionNetworkThreadAsync(clientSession.Details, clientSession.StartListeningAsync(token), token, "Read");
92 | }
93 | catch (Exception e)
94 | {
95 | if(Logger.IsErrorEnabled)
96 | Logger.Error($"Session: {clientSession.Details.ConnectionId} Read thread encountered critical failure. Error: {e}");
97 | throw;
98 | }
99 | }, token);
100 |
101 | Task.Run(async () =>
102 | {
103 | try
104 | {
105 | // Important that NO MATTER WHAT even if some cancel logic fails in this call that
106 | // OnManagedSessionEnded is invoked
107 | await AwaitManagedReadWriteTasksAsync(clientSession, readTask, writeTask, token);
108 | await TryGracefulDisconnectionAsync(clientSession);
109 | }
110 | finally
111 | {
112 | if (Logger.IsDebugEnabled)
113 | Logger.Debug($"Session: {clientSession.Details.ConnectionId} Stopped Network Read/Write.");
114 |
115 | try
116 | {
117 | //Fire off to anyone interested in managed session ending. We should do this before we fully dispose it and remove it from the session collection.
118 | OnManagedSessionEnded?.Invoke(this, new ManagedSessionContextualEventArgs(clientSession));
119 | }
120 | catch(Exception e)
121 | {
122 | if (Logger.IsErrorEnabled)
123 | Logger.Error($"Failed Session: {clientSession.Details.ConnectionId} ended event. Reason: {e}");
124 | }
125 | finally
126 | {
127 | Sessions.TryRemove(clientSession.Details.ConnectionId, out _);
128 |
129 | try
130 | {
131 | clientSession.Dispose();
132 | }
133 | catch(Exception e)
134 | {
135 | if(Logger.IsErrorEnabled)
136 | Logger.Error($"Encountered error in Client: {clientSession.Details.ConnectionId} session disposal. Error: {e}");
137 | throw;
138 | }
139 | }
140 | }
141 | }, token);
142 | }
143 |
144 | private async Task TryGracefulDisconnectionAsync(TManagedSessionType clientSession)
145 | {
146 | try
147 | {
148 | await clientSession.ConnectionService.DisconnectAsync();
149 | }
150 | catch (Exception e)
151 | {
152 | if (Logger.IsErrorEnabled)
153 | Logger.Error($"Session: {clientSession.Details.ConnectionId} was open but failed to disconnect. Reason: {e}");
154 | }
155 | finally
156 | {
157 | try
158 | {
159 | clientSession.Dispose();
160 | }
161 | catch (Exception e)
162 | {
163 | if (Logger.IsErrorEnabled)
164 | Logger.Error($"Session: {clientSession.Details.ConnectionId} failed to dispose. Reason: {e}");
165 | }
166 | }
167 | }
168 |
169 | private async Task AwaitManagedReadWriteTasksAsync(TManagedSessionType clientSession, Task readTask, Task writeTask, CancellationToken token)
170 | {
171 | try
172 | {
173 | await Task.WhenAny(readTask, writeTask);
174 | }
175 | catch (Exception e)
176 | {
177 | //Suppress this exception, we have critical deconstruction code to run.
178 | if (Logger.IsErrorEnabled)
179 | Logger.Error($"Session: {clientSession.Details.ConnectionId} encountered critical failure in awaiting network task. Error: {e}");
180 | }
181 | finally
182 | {
183 |
184 | }
185 | }
186 |
187 | private async Task StartSessionNetworkThreadAsync(SessionDetails details, Task task, CancellationToken token, string taskName)
188 | {
189 | if(details == null) throw new ArgumentNullException(nameof(details));
190 | if(task == null) throw new ArgumentNullException(nameof(task));
191 |
192 | try
193 | {
194 | await task;
195 | }
196 | catch(Exception e)
197 | {
198 | if(Logger.IsErrorEnabled)
199 | Logger.Error($"Session: {details.ConnectionId} encountered error in network {taskName} thread. Error: {e}");
200 | }
201 | finally
202 | {
203 |
204 | }
205 | }
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/src/GladNet.API.Server/Application/IServerApplicationBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 |
7 | namespace GladNet
8 | {
9 | ///
10 | /// Contract for server application types that are listenable.
11 | ///
12 | public interface IServerApplicationListenable
13 | {
14 | ///
15 | /// Begins the listening process of a server application.
16 | /// This is a long running method that likely won't return until application shutdown.
17 | ///
18 | /// The cancellation token.
19 | /// Awaitable
20 | Task BeginListeningAsync(CancellationToken token = default);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/GladNet.API.Server/Events/ManagedSessionContextualEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace GladNet
6 | {
7 | ///
8 | /// for an event involving a managed session.
9 | ///
10 | /// The managed session type.
11 | public class ManagedSessionContextualEventArgs : EventArgs
12 | where TManagedSessionType : ManagedSession
13 | {
14 | ///
15 | /// The managed session this event is associated with.
16 | ///
17 | public TManagedSessionType Session { get; }
18 |
19 | public ManagedSessionContextualEventArgs(TManagedSessionType session)
20 | {
21 | Session = session ?? throw new ArgumentNullException(nameof(session));
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/GladNet.API.Server/GladNet.API.Server.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 | Andrew Blakely, HelloKitty
6 |
7 | GladNet
8 | GladNet (Glader's Library for Advanced Development of Network Emulation Technologies) server API library.
9 | Andrew Blakely
10 | https://github.com/HelloKitty/GladNet3/blob/master/LICENSE
11 | https://github.com/HelloKitty/GladNet3
12 | https://github.com/HelloKitty/GladNet3
13 | git
14 | GladNet Emulation Emulator WoW PSO Network Unity3D Network Networking Netlib GladNet4
15 | GladNet.API.Server
16 | 4.9.45
17 |
18 |
19 |
20 | true
21 | true
22 |
23 |
24 |
25 | C:\Users\Glader\Documents\Github\GladNet3\src\GladNet.API.Server\bin\GladNet.API.Server.xml
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | <_Parameter1>GladNet.Server.DotNetTcpServer
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/GladNet.API.TCP/GladNet.API.TCP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 | Andrew Blakely, HelloKitty
6 |
7 | GladNet
8 | GladNet (Glader's Library for Advanced Development of Network Emulation Technologies) common API library that provides shared API for both client and server.
9 | Andrew Blakely
10 | https://github.com/HelloKitty/GladNet3/blob/master/LICENSE
11 | https://github.com/HelloKitty/GladNet3
12 | https://github.com/HelloKitty/GladNet3
13 | git
14 | GladNet Emulation Emulator WoW PSO Network Unity3D Network Networking Netlib GladNet4
15 | 8.0
16 | GladNet.API.TCP
17 | 4.9.45
18 |
19 |
20 |
21 | true
22 | true
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | <_Parameter1>GladNet.Server.DotNetTcpServer
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/GladNet.API.TCP/Network/SocketConnectionConnectionServiceAdapter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Net.Sockets;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Pipelines.Sockets.Unofficial;
7 |
8 | namespace GladNet
9 | {
10 | ///
11 | /// Implementation of based around
12 | ///
13 | public sealed class SocketConnectionConnectionServiceAdapter : INetworkConnectionService
14 | {
15 | ///
16 | /// Internal socket connection.
17 | ///
18 | private SocketConnection Connection { get; }
19 |
20 | // This is because Connection.Socket.Connected may still be true even after Connection.Socket.ConnectAsync
21 | // down below finishes awaiting.
22 | ///
23 | public bool IsConnected => Connection.Socket.Connected
24 | && Connection.ShutdownKind == PipeShutdownKind.None;
25 |
26 | public SocketConnectionConnectionServiceAdapter(SocketConnection connection)
27 | {
28 | Connection = connection ?? throw new ArgumentNullException(nameof(connection));
29 | }
30 |
31 | ///
32 | public async Task DisconnectAsync()
33 | {
34 | //This may look RIDICULOUS but this seem to be the only way for a server
35 | //to successfully disconnect a client without raising exceptions on the read/write thread
36 | TaskCompletionSource