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 OverloadsSub 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 &amp;
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 StringAs 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 StringAs Boolean
440             Return String.Equals(request, requestStream.GetUTF8String)
441         End Operator
442
443         Public Overloads Shared Operator <>(requestStream As RequestStream, request As StringAs Boolean
444             Return Not String.Equals(request, requestStream.GetUTF8String)
445         End Operator
446     End Class
447 End Namespace