1 | #Region "Microsoft.VisualBasic::a38716614aab2999e8cfa50f8ecbc47e, Microsoft.VisualBasic.Core\Net\Protocol\RequestStream.vb" |
2 | |
3 | ' Author: |
4 | ' |
5 | ' asuka (amethyst.asuka@gcmodeller.org) |
6 | ' xie (genetics@smrucc.org) |
7 | ' xieguigang (xie.guigang@live.com) |
8 | ' |
9 | ' Copyright (c) 2018 GPL3 Licensed |
10 | ' |
11 | ' |
12 | ' GNU GENERAL PUBLIC LICENSE (GPL3) |
13 | ' |
14 | ' |
15 | ' This program is free software: you can redistribute it and/or modify |
16 | ' it under the terms of the GNU General Public License as published by |
17 | ' the Free Software Foundation, either version 3 of the License, or |
18 | ' (at your option) any later version. |
19 | ' |
20 | ' This program is distributed in the hope that it will be useful, |
21 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | ' GNU General Public License for more details. |
24 | ' |
25 | ' You should have received a copy of the GNU General Public License |
26 | ' along with this program. If not, see <http://www.gnu.org/licenses/>. |
27 | |
28 | |
29 | |
30 | ' /********************************************************************************/ |
31 | |
32 | ' Summaries: |
33 | |
34 | ' Class RequestStream |
35 | ' |
36 | ' Properties: BufferLength, ChunkBuffer, FullRead, Protocol, ProtocolCategory |
37 | ' TotalBytes |
38 | ' |
39 | ' Constructor: (+7 Overloads) Sub New |
40 | ' Function: (+2 Overloads) CreatePackage, CreateProtocol, GetRawStream, GetString, GetUTF8String |
41 | ' IsAvaliableStream, (+2 Overloads) LoadObject, Serialize, ToString |
42 | ' Enum Protocols |
43 | ' |
44 | ' |
45 | ' |
46 | ' |
47 | ' |
48 | ' |
49 | ' Properties: IsPing, IsPlantText, IsSSL_PublicToken, IsSSLHandshaking, IsSSLProtocol |
50 | ' TryGetSystemProtocol |
51 | ' |
52 | ' Function: SystemProtocol |
53 | ' Operators: (+3 Overloads) <>, (+3 Overloads) = |
54 | ' |
55 | ' |
56 | ' /********************************************************************************/ |
57 | |
58 | #End Region |
59 | |
60 | Imports System.Runtime.CompilerServices |
61 | Imports System.Text |
62 | Imports System.Xml.Serialization |
63 | Imports Microsoft.VisualBasic.Language |
64 | Imports Microsoft.VisualBasic.Net.Http |
65 | Imports Microsoft.VisualBasic.Scripting.Abstract |
66 | Imports Microsoft.VisualBasic.Serialization.JSON |
67 | Imports Microsoft.VisualBasic.Text |
68 | |
69 | Namespace Net.Protocols |
70 | |
71 | ''' <summary> |
72 | ''' Socket user client => Socket server data request & |
73 | ''' Socket server => Socket user client data response package. |
74 | ''' (Socket客户端 => Socket服务器所发送的数据请求以及从 |
75 | ''' Socket服务器 => Socket客户端所返回数据的数据响应包) |
76 | ''' </summary> |
77 | <Serializable> Public Class RequestStream : Inherits RawStream |
78 | Implements ISerializable |
79 | |
80 | ''' <summary> |
81 | ''' This property indicates the protocol processor module for the server object. |
82 | ''' </summary> |
83 | ''' <returns></returns> |
84 | <XmlAttribute("Entry")> |
85 | Public Property ProtocolCategory As Int64 |
86 | ''' <summary> |
87 | ''' This property indicates which the specifics protocol processor will be used for the incoming client request. |
88 | ''' (协议的头部) |
89 | ''' </summary> |
90 | ''' <returns></returns> |
91 | <XmlAttribute("Protocol")> |
92 | Public Property Protocol As Int64 |
93 | ''' <summary> |
94 | ''' Buffer length of the protocol request raw stream data <see cref="ChunkBuffer"/>.(协议数据的长度) |
95 | ''' </summary> |
96 | ''' <returns></returns> |
97 | <XmlAttribute("bufLen")> |
98 | Public Property BufferLength As Int64 |
99 | ''' <summary> |
100 | ''' The raw stream data of the details data request or the server response data.(协议的具体数据请求) |
101 | ''' </summary> |
102 | ''' <returns></returns> |
103 | <XmlAttribute("rawBuf")> |
104 | Public Property ChunkBuffer As Byte() |
105 | |
106 | ''' <summary> |
107 | ''' <see cref="ChunkBuffer"/>部分的数据是否完整? |
108 | ''' </summary> |
109 | ''' <returns></returns> |
110 | Public ReadOnly Property FullRead As Boolean |
111 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
112 | Get |
113 | Return BufferLength = ChunkBuffer.Length |
114 | End Get |
115 | End Property |
116 | |
117 | Sub New(protocolCategory&, protocol&, buffer As Byte()) |
118 | Me.ProtocolCategory = protocolCategory |
119 | Me.Protocol = protocol |
120 | Me.BufferLength = buffer.Length |
121 | Me.ChunkBuffer = buffer |
122 | End Sub |
123 | |
124 | ''' <summary> |
125 | ''' 构建一个无参数的网络协议对象 |
126 | ''' </summary> |
127 | ''' <param name="ProtocolCategory"></param> |
128 | ''' <param name="Protocol"></param> |
129 | Sub New(protocolCategory&, protocol&) |
130 | Call Me.New(protocolCategory, protocol, New Byte() {}) |
131 | End Sub |
132 | |
133 | ''' <summary> |
134 | ''' The default text encoding is <see cref="System.Text.Encoding.UTF8"/> |
135 | ''' </summary> |
136 | ''' <param name="ProtocolCategory"></param> |
137 | ''' <param name="Protocol"></param> |
138 | ''' <param name="str">Protocol request argument parameters</param> |
139 | Sub New(ProtocolCategory As Long, Protocol As Long, str As String) |
140 | Call Me.New(ProtocolCategory, Protocol, UTF8WithoutBOM.GetBytes(str)) |
141 | End Sub |
142 | |
143 | Sub New(ProtocolCategory As Long, Protocol As Long, str As String, encoding As Encoding) |
144 | Call Me.New(ProtocolCategory, Protocol, encoding.GetBytes(str)) |
145 | End Sub |
146 | |
147 | Sub New(ProtocolCategory As Long, Protocol As Long, buffer As ISerializable) |
148 | Call Me.New(ProtocolCategory, Protocol, buffer.Serialize) |
149 | End Sub |
150 | |
151 | ''' <summary> |
152 | ''' 其余的协议参数都是值 <see cref="HTTP_RFC.RFC_OK"/> |
153 | ''' </summary> |
154 | ''' <param name="data"></param> |
155 | Sub New(data As String) |
156 | Call Me.New(HTTP_RFC.RFC_OK, HTTP_RFC.RFC_OK, data) |
157 | End Sub |
158 | |
159 | ''' <summary> |
160 | ''' Deserialize (当还有剩余数据的时候会将数据进行剪裁) |
161 | ''' </summary> |
162 | ''' <param name="rawStream"></param> |
163 | Sub New(rawStream As Byte()) |
164 | Call MyBase.New(rawStream) |
165 | |
166 | Dim bitChunk As Byte() = New Byte(INT64 - 1) {} |
167 | Dim p As int = Scan0 |
168 | |
169 | Call Array.ConstrainedCopy(rawStream, ++p, bitChunk, Scan0, INT64) |
170 | Me.ProtocolCategory = BitConverter.ToInt64(bitChunk, Scan0) |
171 | |
172 | Call Array.ConstrainedCopy(rawStream, ++(p + INT64), bitChunk, Scan0, INT64) |
173 | Me.Protocol = BitConverter.ToInt64(bitChunk, Scan0) |
174 | |
175 | bitChunk = New Byte(INT64 - 1) {} |
176 | Call Array.ConstrainedCopy(rawStream, p + INT64, bitChunk, Scan0, INT64) |
177 | |
178 | Me.BufferLength = BitConverter.ToInt64(bitChunk, Scan0) |
179 | Me.ChunkBuffer = New Byte(Me.BufferLength - 1) {} |
180 | |
181 | If CLng(p + INT64) + BufferLength > rawStream.Length Then |
182 | ' 越界了,则数据没有读完 |
183 | ChunkBuffer = New Byte() {} |
184 | Else |
185 | Call Array.ConstrainedCopy( |
186 | rawStream, p, |
187 | ChunkBuffer, Scan0, BufferLength |
188 | ) |
189 | End If |
190 | End Sub |
191 | |
192 | ''' <summary> |
193 | ''' 默认是使用UTF8编码来编码字符串的 |
194 | ''' </summary> |
195 | ''' <returns></returns> |
196 | ''' |
197 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
198 | Public Function GetUTF8String() As String |
199 | Return UTF8WithoutBOM.GetString(ChunkBuffer) |
200 | End Function |
201 | |
202 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
203 | Public Function GetString(encoding As Encoding) As String |
204 | Return encoding.GetString(ChunkBuffer) |
205 | End Function |
206 | |
207 | ''' <summary> |
208 | ''' 将数据首先生成字符串,然后根据函数指针<paramref name="handler"/>句柄的描述从字符串之中反序列化加载对象 |
209 | ''' </summary> |
210 | ''' <typeparam name="T"></typeparam> |
211 | ''' <param name="handler"></param> |
212 | ''' <returns></returns> |
213 | ''' |
214 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
215 | Public Function LoadObject(Of T)(handler As LoadObject(Of T)) As T |
216 | Return handler(GetUTF8String) |
217 | End Function |
218 | |
219 | ''' <summary> |
220 | ''' json |
221 | ''' </summary> |
222 | ''' <typeparam name="T"></typeparam> |
223 | ''' <returns></returns> |
224 | ''' |
225 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
226 | Public Function LoadObject(Of T)() As T |
227 | Return GetUTF8String.LoadJSON(Of T) |
228 | End Function |
229 | |
230 | ''' <summary> |
231 | ''' 从原始数据流<see cref="ChunkBuffer"/>之中进行反序列化得到一个嵌套的数据串流对象 |
232 | ''' </summary> |
233 | ''' <typeparam name="TStream"></typeparam> |
234 | ''' <returns></returns> |
235 | Public Overloads Function GetRawStream(Of TStream As RawStream)() As TStream |
236 | Return GetRawStream(Of TStream)(rawStream:=ChunkBuffer) |
237 | End Function |
238 | |
239 | Public Overrides Function ToString() As String |
240 | Dim str As String = $"(string) {NameOf(ChunkBuffer)}:={GetUTF8String()}; {TotalBytes()} bytes" |
241 | Return $"{NameOf(ProtocolCategory)}:={ProtocolCategory}; {NameOf(Protocol)}:={Protocol}; {NameOf(BufferLength)}:={BufferLength}; // {str}" |
242 | End Function |
243 | |
244 | ''' <summary> |
245 | ''' 这个函数是使用json序列化参数信息的 |
246 | ''' </summary> |
247 | ''' <typeparam name="T"></typeparam> |
248 | ''' <param name="category"></param> |
249 | ''' <param name="protocol"></param> |
250 | ''' <param name="params"></param> |
251 | ''' <returns></returns> |
252 | Public Shared Function CreateProtocol(Of T)(category As Long, protocol As Long, params As T) As RequestStream |
253 | Dim json As String = params.GetJson |
254 | Return New RequestStream(category, protocol, json) |
255 | End Function |
256 | |
257 | ''' <summary> |
258 | ''' 服务器端返回数据所使用的,默认使用json序列化,所有的标签为<see cref="HTTP_RFC.RFC_OK"/> |
259 | ''' </summary> |
260 | ''' <typeparam name="T"></typeparam> |
261 | ''' <param name="obj"></param> |
262 | ''' <returns></returns> |
263 | Public Shared Function CreatePackage(Of T)(obj As T) As RequestStream |
264 | Return New RequestStream(HTTP_RFC.RFC_OK, HTTP_RFC.RFC_OK, obj.GetJson) |
265 | End Function |
266 | |
267 | ''' <summary> |
268 | ''' 服务器端返回数据所使用的,所有的标签为<see cref="HTTP_RFC.RFC_OK"/> |
269 | ''' </summary> |
270 | ''' <param name="pack"></param> |
271 | ''' <returns></returns> |
272 | Public Shared Function CreatePackage(pack As Byte()) As RequestStream |
273 | Return New RequestStream(HTTP_RFC.RFC_OK, HTTP_RFC.RFC_OK, pack) |
274 | End Function |
275 | |
276 | Private Shared ReadOnly ___offset As Byte() = New Byte() {RequestStream.BITWISE_FLAG} |
277 | |
278 | Const BITWISE_FLAG As Byte = 255 |
279 | Const MIN_LEN As Integer = INT64 + 1 + INT64 + 1 + INT64 |
280 | |
281 | Public Shared Function IsAvaliableStream(stream As Byte()) As Boolean |
282 | If stream.Length < MIN_LEN Then |
283 | Return False |
284 | End If |
285 | |
286 | If stream(INT64) <> BITWISE_FLAG OrElse stream(INT64 + 1 + INT64) <> BITWISE_FLAG Then |
287 | Return False |
288 | Else |
289 | Return True |
290 | End If |
291 | End Function |
292 | |
293 | ''' <summary> |
294 | ''' 注意:在协议头部之间还存在着一个字节的offset,这个字节的值为255 |
295 | ''' </summary> |
296 | ''' <returns></returns> |
297 | Public ReadOnly Property TotalBytes() As Long |
298 | Get |
299 | Return INT64 + 1 + ' ProtocolCategory |
300 | INT64 + 1 + ' Protocol |
301 | INT64 + ' BufferLength |
302 | BufferLength ' ChunkBuffer |
303 | End Get |
304 | End Property |
305 | |
306 | ''' <summary> |
307 | ''' 执行序列化进行网络之间的数据传输 |
308 | ''' </summary> |
309 | ''' <returns></returns> |
310 | Public Overrides Function Serialize() As Byte() Implements ISerializable.Serialize |
311 | Dim ProtocolCategory As Byte() = BitConverter.GetBytes(Me.ProtocolCategory) |
312 | Dim Protocol As Byte() = BitConverter.GetBytes(Me.Protocol) |
313 | Dim BufferLength As Byte() = BitConverter.GetBytes(Me.BufferLength) |
314 | Dim bufs As Byte() = New Byte(TotalBytes - 1) {} |
315 | Dim p As int = Scan0 |
316 | Dim l As New int |
317 | |
318 | Call Array.ConstrainedCopy(ProtocolCategory, Scan0, bufs, p << (l = ProtocolCategory.Length), l) |
319 | Call Array.ConstrainedCopy(___offset, Scan0, bufs, ++p, 1) |
320 | Call Array.ConstrainedCopy(Protocol, Scan0, bufs, p << (l = Protocol.Length), l) |
321 | Call Array.ConstrainedCopy(___offset, Scan0, bufs, ++p, 1) |
322 | Call Array.ConstrainedCopy(BufferLength, Scan0, bufs, p << (l = BufferLength.Length), l) |
323 | Call Array.ConstrainedCopy(Me.ChunkBuffer, Scan0, bufs, p << (l = Me.BufferLength), l) |
324 | |
325 | Return bufs |
326 | End Function |
327 | |
328 | ''' <summary> |
329 | ''' 系统里面最基本的基本数据协议 |
330 | ''' </summary> |
331 | Public Const SYS_PROTOCOL As Long = -8888888L |
332 | |
333 | ''' <summary> |
334 | ''' 最基本的Socket数据串流协议 |
335 | ''' </summary> |
336 | Public Enum Protocols As Long |
337 | OK = HTTP_RFC.RFC_OK |
338 | |
339 | Ping = 10L |
340 | ''' <summary> |
341 | ''' 私有密匙加密 |
342 | ''' </summary> |
343 | SSL = -107L |
344 | SSLHandshake = -200L |
345 | ''' <summary> |
346 | ''' 公共密匙加密 |
347 | ''' </summary> |
348 | SSL_PublicToken = -405L |
349 | ''' <summary> |
350 | ''' 无效的数字证书 |
351 | ''' </summary> |
352 | InvalidCertificates = -404L |
353 | |
354 | NOT_SYS = 0L |
355 | End Enum |
356 | |
357 | Public Shared Function SystemProtocol(Protocol As Protocols, Message As String) As RequestStream |
358 | Return New RequestStream(SYS_PROTOCOL, Protocol, Message) |
359 | End Function |
360 | |
361 | Public ReadOnly Property TryGetSystemProtocol As Protocols |
362 | Get |
363 | Try |
364 | Return CType(Protocol, Protocols) |
365 | Catch ex As Exception |
366 | Return Protocols.NOT_SYS |
367 | End Try |
368 | End Get |
369 | End Property |
370 | |
371 | Public ReadOnly Property IsPing As Boolean |
372 | Get |
373 | Return ProtocolCategory = SYS_PROTOCOL AndAlso Protocol = Protocols.Ping |
374 | End Get |
375 | End Property |
376 | |
377 | ''' <summary> |
378 | ''' 这个请求数据是一个SSL加密数据(使用用户的私有密匙) |
379 | ''' </summary> |
380 | ''' <returns></returns> |
381 | Public ReadOnly Property IsSSLProtocol As Boolean |
382 | Get |
383 | Return ProtocolCategory = SYS_PROTOCOL AndAlso Protocol = Protocols.SSL |
384 | End Get |
385 | End Property |
386 | |
387 | ''' <summary> |
388 | ''' 使用公共密匙 |
389 | ''' </summary> |
390 | ''' <returns></returns> |
391 | Public ReadOnly Property IsSSL_PublicToken As Boolean |
392 | Get |
393 | Return ProtocolCategory = SYS_PROTOCOL AndAlso Protocol = Protocols.SSL_PublicToken |
394 | End Get |
395 | End Property |
396 | |
397 | ''' <summary> |
398 | ''' 这个数据仅仅是一个文本,没有包含有任何协议头数据 |
399 | ''' </summary> |
400 | ''' <returns></returns> |
401 | Public ReadOnly Property IsPlantText As Boolean |
402 | Get |
403 | Return ProtocolCategory = Scan0 AndAlso Protocol = Scan0 |
404 | End Get |
405 | End Property |
406 | |
407 | ''' <summary> |
408 | ''' 这个请求数据是否为握手协议 |
409 | ''' </summary> |
410 | ''' <returns></returns> |
411 | Public ReadOnly Property IsSSLHandshaking As Boolean |
412 | Get |
413 | Return ProtocolCategory = SYS_PROTOCOL AndAlso Protocol = Protocols.SSLHandshake |
414 | End Get |
415 | End Property |
416 | |
417 | ''' <summary> |
418 | ''' 简单的字符串等价 |
419 | ''' </summary> |
420 | ''' <param name="a"></param> |
421 | ''' <param name="b"></param> |
422 | ''' <returns></returns> |
423 | Public Overloads Shared Operator =(a As RequestStream, b As RequestStream) As Boolean |
424 | Return String.Equals(a.GetUTF8String, b.GetUTF8String) |
425 | End Operator |
426 | |
427 | Public Overloads Shared Operator <>(a As RequestStream, b As RequestStream) As Boolean |
428 | Return Not String.Equals(a.GetUTF8String, b.GetUTF8String) |
429 | End Operator |
430 | |
431 | Public Overloads Shared Operator =(request As String, requestStream As RequestStream) As Boolean |
432 | Return String.Equals(request, requestStream.GetUTF8String) |
433 | End Operator |
434 | |
435 | Public Overloads Shared Operator <>(request As String, requestStream As RequestStream) As Boolean |
436 | Return Not String.Equals(request, requestStream.GetUTF8String) |
437 | End Operator |
438 | |
439 | Public Overloads Shared Operator =(requestStream As RequestStream, request As String) As Boolean |
440 | Return String.Equals(request, requestStream.GetUTF8String) |
441 | End Operator |
442 | |
443 | Public Overloads Shared Operator <>(requestStream As RequestStream, request As String) As Boolean |
444 | Return Not String.Equals(request, requestStream.GetUTF8String) |
445 | End Operator |
446 | End Class |
447 | End Namespace |