1 #Region "Microsoft.VisualBasic::e9fc2b90e6ed847e0a43175fe081b3d1, Microsoft.VisualBasic.Core\Net\Protocol\Reflection\ProtocolHandler.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 ProtocolHandler
35     
36     '         Properties: DeclaringType, ProtocolEntry
37     
38     '         Constructor: (+1 OverloadsSub New
39     '         FunctionGetMethod, HandlePush, HandleRequest, method1, method2
40     '                   (+2 Overloads) SafelyCreateObject, ToString
41     
42     
43     ' /********************************************************************************/
44
45 #End Region
46
47 Imports System.Reflection
48 Imports System.Runtime.CompilerServices
49 Imports Microsoft.VisualBasic.Net.Abstract
50 Imports Microsoft.VisualBasic.Net.Http
51 Imports Microsoft.VisualBasic.Net.Tcp
52 Imports TcpEndPoint = System.Net.IPEndPoint
53
54 Namespace Net.Protocols.Reflection
55
56     ''' <summary>
57     ''' 这个模块只处理<see cref="DataRequestHandler"/>类型的接口
58     ''' 
59     ''' ```vbnet
60     ''' <see cref="System.Delegate"/> Function(request As <see cref="RequestStream"/>, RemoteAddress As <see cref="TcpEndPoint"/>) As <see cref="RequestStream"/>
61     ''' ```
62     ''' </summary>
63     Public Class ProtocolHandler : Inherits IProtocolHandler
64
65         Protected Protocols As Dictionary(Of Long, DataRequestHandler)
66         ''' <summary>
67         ''' 这个类型建议一般为某种枚举类型
68         ''' </summary>
69         ''' <returns></returns>
70         Public ReadOnly Property DeclaringType As Type
71         Public Overrides ReadOnly Property ProtocolEntry As Long
72
73         Public Overrides Function ToString() As String
74             Return $"*{ProtocolEntry}   ---> {DeclaringType.FullName}  //{Protocols.Count} Protocols."
75         End Function
76
77         Const AllInstanceMethod As BindingFlags =
78             BindingFlags.Public Or
79             BindingFlags.NonPublic Or
80             BindingFlags.Instance
81
82         ''' <summary>
83         ''' 请注意,假若没有在目标的类型定义之中查找出入口点的定义,则这个构造函数会报错,
84         ''' 假若需要安全的创建对象,可以使用<see cref="ProtocolHandler.SafelyCreateObject(Of T)(T)"/>函数
85         ''' </summary>
86         ''' <param name="obj">Protocol的实例</param>
87         Sub New(obj As Object)
88             Dim type As Type = obj.GetType
89             Dim entry As Protocol = Protocol.GetProtocolCategory(type)
90
91             Me.DeclaringType = entry?.DeclaringType
92             Me.ProtocolEntry = entry?.EntryPoint
93
94             ' 解析出所有符合 WrapperClassTools.Net.DataRequestHandler 接口类型的函数方法
95             Dim Methods = type.GetMethods(bindingAttr:=AllInstanceMethod)
96             Dim LQuery = (From entryPoint As MethodInfo
97                           In Methods
98                           Let Protocol As Protocol = Protocol.GetEntryPoint(entryPoint)
99                           Let method As DataRequestHandler = GetMethod(obj, entryPoint)
100                           Where Not (Protocol Is NothingAndAlso
101                               Not method Is Nothing
102                           Select Protocol, entryPoint, method)
103
104             Me.Protocols = LQuery.ToDictionary(Function(element)
105                                                    Return element.Protocol.EntryPoint
106                                                End Function,
107                                                Function(element) element.method)
108         End Sub
109
110         ''' <summary>
111         ''' 失败会返回空值
112         ''' </summary>
113         ''' <typeparam name="T"></typeparam>
114         ''' <param name="App"></param>
115         ''' <returns></returns>
116         Public Shared Function SafelyCreateObject(Of T As Class)(App As T) As ProtocolHandler
117             Try
118                 Return New ProtocolHandler(App)
119             Catch ex As Exception
120                 Return Nothing
121             End Try
122         End Function
123
124         Public Shared Function SafelyCreateObject(App As ObjectAs ProtocolHandler
125             Try
126                 Return New ProtocolHandler(App)
127             Catch ex As Exception
128                 Return Nothing
129             End Try
130         End Function
131
132         <MethodImpl(MethodImplOptions.AggressiveInlining)>
133         Public Function HandlePush(uid As Long, request As RequestStream) As RequestStream
134             Return HandleRequest(request, Nothing)
135         End Function
136
137         ''' <summary>
138         ''' Handle the data request from the client for socket events: <see cref="TcpServicesSocket.Responsehandler"/>.
139         ''' </summary>
140         ''' <param name="request">The request stream object which contains the commands from the client</param>
141         ''' <param name="remoteDevcie">The IPAddress of the target incoming client data request.</param>
142         ''' <returns></returns>
143         Public Overrides Function HandleRequest(request As RequestStream, remoteDevcie As TcpEndPoint) As RequestStream
144             If request.ProtocolCategory <> Me.ProtocolEntry Then
145 #If DEBUG Then
146                 Call $"Protocol_entry:={request.ProtocolCategory} was not found!".__DEBUG_ECHO
147 #End If
148                 Return NetResponse.RFC_VERSION_NOT_SUPPORTED
149             End If
150
151             If Not Me.Protocols.ContainsKey(request.Protocol) Then
152 #If DEBUG Then
153                 Call $"Protocol:={request.Protocol} was not found!".__DEBUG_ECHO
154 #End If
155                 ' 没有找到相对应的协议处理逻辑,则没有实现相对应的数据协议处理方法
156                 Return NetResponse.RFC_NOT_IMPLEMENTED
157             End If
158
159             Dim EntryPoint As DataRequestHandler = Me.Protocols(request.Protocol)
160             Dim value As RequestStream = EntryPoint(request, remoteDevcie)
161             Return value
162         End Function
163
164         Private Shared Function GetMethod(obj As Object, entryPoint As MethodInfo) As DataRequestHandler
165             Dim parameters As ParameterInfo() = entryPoint.GetParameters
166
167             If Not entryPoint.ReturnType.Equals(GetType(RequestStream)) Then
168                 Return Nothing
169             ElseIf parameters.Length > 2 Then
170                 Return Nothing
171             End If
172
173             If parameters.Length = 0 Then
174                 Return AddressOf New ProtocolInvoker(obj, entryPoint).InvokeProtocol0
175             ElseIf parameters.Length = 1 Then
176                 Return method1(obj, entryPoint, parameters)
177             ElseIf parameters.Length = 2 Then
178                 Return method2(obj, entryPoint, parameters)
179             End If
180
181             Return Nothing
182         End Function
183
184         Private Shared Function method2(obj As Object, entryPoint As MethodInfo, parameters As ParameterInfo()) As DataRequestHandler
185             If (Not parameters.First.ParameterType.Equals(GetType(RequestStream)) OrElse
186                 Not parameters.Last.ParameterType.Equals(GetType(TcpEndPoint))) Then
187                 Return Nothing
188             Else
189                 Return AddressOf New ProtocolInvoker(obj, entryPoint).InvokeProtocol2
190             End If
191         End Function
192
193         Private Shared Function method1(obj As Object, entryPoint As MethodInfo, parameters As ParameterInfo()) As DataRequestHandler
194             If Not parameters.First.ParameterType.Equals(GetType(RequestStream)) Then
195                 Return Nothing
196             Else
197                 Return AddressOf New ProtocolInvoker(obj, entryPoint).InvokeProtocol1
198             End If
199         End Function
200
201         <MethodImpl(MethodImplOptions.AggressiveInlining)>
202         Public Shared Narrowing Operator CType(handler As ProtocolHandler) As DataRequestHandler
203             Return AddressOf handler.HandleRequest
204         End Operator
205     End Class
206 End Namespace