88 using Newtonsoft . Json ;
99 using System . Threading . Tasks ;
1010 using System . Collections . Concurrent ;
11- using Newtonsoft . Json . Linq ;
11+ using Newtonsoft . Json . Linq ;
12+ using System . Threading ;
1213
1314 public class Handler
1415 {
@@ -26,7 +27,7 @@ static Handler()
2627 //current = new Handler(Guid.NewGuid().ToString());
2728 _defaultSessionId = Guid . NewGuid ( ) . ToString ( ) ;
2829 _sessionHandlers = new ConcurrentDictionary < string , Handler > ( ) ;
29- _sessionHandlers [ _defaultSessionId ] = new Handler ( _defaultSessionId ) ;
30+ _sessionHandlers [ _defaultSessionId ] = new Handler ( _defaultSessionId ) ;
3031 }
3132
3233 private Handler ( string sessionId )
@@ -55,7 +56,7 @@ public static Handler GetSessionHandler(string sessionId)
5556 {
5657 return _sessionHandlers . GetOrAdd ( sessionId , new Handler ( sessionId ) ) ;
5758 }
58-
59+
5960 /// <summary>
6061 /// gets the default session
6162 /// </summary>
@@ -72,7 +73,7 @@ public static Handler GetSessionHandler()
7273 public static void DestroySession ( string sessionId )
7374 {
7475 Handler h ;
75- _sessionHandlers . TryRemove ( sessionId , out h ) ;
76+ _sessionHandlers . TryRemove ( sessionId , out h ) ;
7677 h . Handlers . Clear ( ) ;
7778 h . MetaData . Services . Clear ( ) ;
7879 }
@@ -92,7 +93,7 @@ public void Destroy()
9293 /// <summary>
9394 /// The sessionID of this Handler
9495 /// </summary>
95- public string SessionId { get ; private set ; }
96+ public string SessionId { get ; private set ; }
9697
9798 private static ConcurrentDictionary < int , object > RpcContexts = new ConcurrentDictionary < int , object > ( ) ;
9899 private static ConcurrentDictionary < int , JsonRpcException > RpcExceptions = new ConcurrentDictionary < int , JsonRpcException > ( ) ;
@@ -104,7 +105,7 @@ public void Destroy()
104105 /// <returns></returns>
105106 public static object RpcContext ( )
106107 {
107- if ( Task . CurrentId == null )
108+ if ( Task . CurrentId == null )
108109 return null ;
109110
110111 if ( RpcContexts . ContainsKey ( Task . CurrentId . Value ) == false )
@@ -140,7 +141,7 @@ private void RemoveRpcException()
140141 private AustinHarris . JsonRpc . PreProcessHandler externalPreProcessingHandler ;
141142 private Func < JsonRequest , JsonRpcException , JsonRpcException > externalErrorHandler ;
142143 private Func < string , JsonRpcException , JsonRpcException > parseErrorHandler ;
143- private Dictionary < string , Delegate > Handlers { get ; set ; }
144+ private Dictionary < string , Delegate > Handlers { get ; set ; }
144145 #endregion
145146
146147 /// <summary>
@@ -180,15 +181,26 @@ public void UnRegister(string key)
180181 /// <param name="Rpc">JsonRpc Request to be processed</param>
181182 /// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param>
182183 /// <returns></returns>
183- public JsonResponse Handle ( JsonRequest Rpc , Object RpcContext = null )
184+ public JsonResponse Handle ( JsonRequest Rpc , Object RpcContext = null , Action < JsonResponse > callback = null )
184185 {
186+ //empty delegate declaration if callback is not provided
187+ if ( null == callback )
188+ {
189+ callback = delegate ( JsonResponse a ) { } ;
190+ }
191+
185192 AddRpcContext ( RpcContext ) ;
186193
187194 var preProcessingException = PreProcess ( Rpc , RpcContext ) ;
188195 if ( preProcessingException != null )
189196 {
190- return new JsonResponse ( ) { Error = preProcessingException ,
191- Id = Rpc . Id } ;
197+ JsonResponse response = new JsonResponse ( )
198+ {
199+ Error = preProcessingException ,
200+ Id = Rpc . Id
201+ } ;
202+ callback . Invoke ( response ) ;
203+ return response ;
192204 }
193205
194206 SMDService metadata = null ;
@@ -198,25 +210,32 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
198210
199211 if ( haveDelegate == false || haveMetadata == false || metadata == null || handle == null )
200212 {
201- return new JsonResponse ( ) { Result = null , Error = new JsonRpcException ( - 32601 , "Method not found" , "The method does not exist / is not available." ) , Id = Rpc . Id } ;
213+ JsonResponse response = new JsonResponse ( )
214+ {
215+ Result = null ,
216+ Error = new JsonRpcException ( - 32601 , "Method not found" , "The method does not exist / is not available." ) ,
217+ Id = Rpc . Id
218+ } ;
219+ callback . Invoke ( response ) ;
220+ return response ;
202221 }
203222
204223 bool isJObject = Rpc . Params is Newtonsoft . Json . Linq . JObject ;
205224 bool isJArray = Rpc . Params is Newtonsoft . Json . Linq . JArray ;
206225 object [ ] parameters = null ;
207226 bool expectsRefException = false ;
208227 var metaDataParamCount = metadata . parameters . Count ( x => x != null ) ;
209-
228+
210229 var getCount = Rpc . Params as ICollection ;
211230 var loopCt = 0 ;
212-
231+
213232 if ( getCount != null )
214233 {
215234 loopCt = getCount . Count ;
216235 }
217236
218237 var paramCount = loopCt ;
219- if ( paramCount == metaDataParamCount - 1 && metadata . parameters [ metaDataParamCount - 1 ] . ObjectType . Name . Contains ( typeof ( JsonRpcException ) . Name ) )
238+ if ( paramCount == metaDataParamCount - 1 && metadata . parameters [ metaDataParamCount - 1 ] . ObjectType . Name . Contains ( typeof ( JsonRpcException ) . Name ) )
220239 {
221240 paramCount ++ ;
222241 expectsRefException = true ;
@@ -234,7 +253,7 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
234253 for ( int i = 0 ; i < loopCt ; i ++ )
235254 {
236255 parameters [ i ] = CleanUpParameter ( jarr [ i ] , metadata . parameters [ i ] ) ;
237- }
256+ }
238257 }
239258 else if ( isJObject )
240259 {
@@ -249,16 +268,18 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
249268 {
250269 if ( asDict . ContainsKey ( metadata . parameters [ i ] . Name ) == false )
251270 {
252- return new JsonResponse ( )
271+ JsonResponse response = new JsonResponse ( )
253272 {
254273 Error = ProcessException ( Rpc ,
255274 new JsonRpcException ( - 32602 ,
256275 "Invalid params" ,
257276 string . Format ( "Named parameter '{0}' was not present." ,
258277 metadata . parameters [ i ] . Name )
259- ) )
260- , Id = Rpc . Id
278+ ) ) ,
279+ Id = Rpc . Id
261280 } ;
281+ callback . Invoke ( response ) ;
282+ return response ;
262283 }
263284 parameters [ i ] = CleanUpParameter ( jo [ metadata . parameters [ i ] . Name ] , metadata . parameters [ i ] ) ;
264285 }
@@ -282,7 +303,7 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
282303
283304 if ( missingParamsCount > metadata . defaultValues . Length )
284305 {
285- return new JsonResponse
306+ JsonResponse response = new JsonResponse
286307 {
287308 Error = ProcessException ( Rpc ,
288309 new JsonRpcException ( - 32602 ,
@@ -293,12 +314,14 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
293314 ) ) ,
294315 Id = Rpc . Id
295316 } ;
317+ callback . Invoke ( response ) ;
318+ return response ;
296319 }
297320 }
298-
321+
299322 if ( parameters . Length != metaDataParamCount )
300323 {
301- return new JsonResponse ( )
324+ JsonResponse response = new JsonResponse ( )
302325 {
303326 Error = ProcessException ( Rpc ,
304327 new JsonRpcException ( - 32602 ,
@@ -309,46 +332,68 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
309332 ) ) ,
310333 Id = Rpc . Id
311334 } ;
335+ callback . Invoke ( response ) ;
336+ return response ;
312337 }
313338
314339 try
315340 {
341+ //callback is stored to thread's local storage in order to get it directly from concrete JsonRpcService method implementation
342+ if ( null != callback )
343+ {
344+ Thread . SetData ( Thread . GetNamedDataSlot ( "Callback" ) , callback ) ;
345+ }
316346 var results = handle . DynamicInvoke ( parameters ) ;
317347 var last = parameters . LastOrDefault ( ) ;
318348 JsonRpcException contextException ;
319349 if ( Task . CurrentId . HasValue && RpcExceptions . TryRemove ( Task . CurrentId . Value , out contextException ) )
320350 {
321- return new JsonResponse ( ) { Error = ProcessException ( Rpc , contextException ) , Id = Rpc . Id } ;
351+ JsonResponse response = new JsonResponse ( ) { Error = ProcessException ( Rpc , contextException ) , Id = Rpc . Id } ;
352+ callback . Invoke ( response ) ;
353+ return response ;
322354 }
323355 if ( expectsRefException && last != null && last is JsonRpcException )
324356 {
325- return new JsonResponse ( ) { Error = ProcessException ( Rpc , last as JsonRpcException ) , Id = Rpc . Id } ;
357+ JsonResponse response = new JsonResponse ( ) { Error = ProcessException ( Rpc , last as JsonRpcException ) , Id = Rpc . Id } ;
358+ callback . Invoke ( response ) ;
359+ return response ;
326360 }
327361
328362 return new JsonResponse ( ) { Result = results } ;
329363 }
330364 catch ( Exception ex )
331365 {
366+ JsonResponse response ;
332367 if ( ex is TargetParameterCountException )
333368 {
334- return new JsonResponse ( ) { Error = ProcessException ( Rpc , new JsonRpcException ( - 32602 , "Invalid params" , ex ) ) } ;
369+ response = new JsonResponse ( ) { Error = ProcessException ( Rpc , new JsonRpcException ( - 32602 , "Invalid params" , ex ) ) } ;
370+ callback . Invoke ( response ) ;
371+ return response ;
335372 }
336373
337374 // We really dont care about the TargetInvocationException, just pass on the inner exception
338375 if ( ex is JsonRpcException )
339376 {
340- return new JsonResponse ( ) { Error = ProcessException ( Rpc , ex as JsonRpcException ) } ;
377+ response = new JsonResponse ( ) { Error = ProcessException ( Rpc , ex as JsonRpcException ) } ;
378+ callback . Invoke ( response ) ;
379+ return response ;
341380 }
342381 if ( ex . InnerException != null && ex . InnerException is JsonRpcException )
343382 {
344- return new JsonResponse ( ) { Error = ProcessException ( Rpc , ex . InnerException as JsonRpcException ) } ;
383+ response = new JsonResponse ( ) { Error = ProcessException ( Rpc , ex . InnerException as JsonRpcException ) } ;
384+ callback . Invoke ( response ) ;
385+ return response ;
345386 }
346387 else if ( ex . InnerException != null )
347388 {
348- return new JsonResponse ( ) { Error = ProcessException ( Rpc , new JsonRpcException ( - 32603 , "Internal Error" , ex . InnerException ) ) } ;
389+ response = new JsonResponse ( ) { Error = ProcessException ( Rpc , new JsonRpcException ( - 32603 , "Internal Error" , ex . InnerException ) ) } ;
390+ callback . Invoke ( response ) ;
391+ return response ;
349392 }
350393
351- return new JsonResponse ( ) { Error = ProcessException ( Rpc , new JsonRpcException ( - 32603 , "Internal Error" , ex ) ) } ;
394+ response = new JsonResponse ( ) { Error = ProcessException ( Rpc , new JsonRpcException ( - 32603 , "Internal Error" , ex ) ) } ;
395+ callback . Invoke ( response ) ;
396+ return response ;
352397 }
353398 finally
354399 {
@@ -371,14 +416,14 @@ private void RemoveRpcContext()
371416 RpcContexts . TryRemove ( id , out va ) ;
372417 }
373418 }
374-
375- private JsonRpcException ProcessException ( JsonRequest req , JsonRpcException ex )
419+
420+ private JsonRpcException ProcessException ( JsonRequest req , JsonRpcException ex )
376421 {
377- if ( externalErrorHandler != null )
378- return externalErrorHandler ( req , ex ) ;
422+ if ( externalErrorHandler != null )
423+ return externalErrorHandler ( req , ex ) ;
379424 return ex ;
380425 }
381- internal JsonRpcException ProcessParseException ( string req , JsonRpcException ex )
426+ internal JsonRpcException ProcessParseException ( string req , JsonRpcException ex )
382427 {
383428 if ( parseErrorHandler != null )
384429 return parseErrorHandler ( req , ex ) ;
@@ -392,7 +437,7 @@ internal void SetParseErrorHandler(Func<string, JsonRpcException, JsonRpcExcepti
392437 {
393438 parseErrorHandler = handler ;
394439 }
395-
440+
396441 #endregion
397442 private object CleanUpParameter ( object p , SMDAdditionalParameters metaData )
398443 {
@@ -404,7 +449,7 @@ private object CleanUpParameter(object p, SMDAdditionalParameters metaData)
404449 }
405450 if ( bob != null )
406451 {
407-
452+
408453 // Avoid calling DeserializeObject on types that JValue has an explicit converter for
409454 // try to optimize for the most common types
410455 if ( metaData . ObjectType == typeof ( string ) ) return ( string ) bob ;
@@ -442,8 +487,8 @@ private object CleanUpParameter(object p, SMDAdditionalParameters metaData)
442487 {
443488 try
444489 {
445- if ( p is string )
446- return JsonConvert . DeserializeObject ( ( string ) p , metaData . ObjectType ) ;
490+ if ( p is string )
491+ return JsonConvert . DeserializeObject ( ( string ) p , metaData . ObjectType ) ;
447492 return JsonConvert . DeserializeObject ( p . ToString ( ) , metaData . ObjectType ) ;
448493 }
449494 catch ( Exception ex )
0 commit comments