public ServerException(DtpException exception) : base( $"Remote connection threw an error when executing function \"{exception.FunctionName}\": {exception.Message}", new Exception(exception.Message) ) { ServerMessage = $"Function name: {exception.FunctionName}\r\nParameters: {(string.IsNullOrEmpty(exception.ParameterInformation) ? "null" : exception.ParameterInformation)}\r\n" + exception.StackTrace + "\r\n--------- FINISH SERVER STACK TRACE ---------\r\n"; var field = typeof(Exception).GetField("_remoteStackTraceString", BindingFlags.NonPublic | BindingFlags.Instance); field.SetValue(this, ServerMessage); //change stack trace with a small hack }
/// <summary> /// Process the received data from a <see cref="DtpFactory" /> /// </summary> /// <param name="data">The data which was given using the <see cref="DtpFactory.SendDataAction" /> delegate</param> /// <param name="start">The start position of the byte array</param> /// <returns>Returns the response which must get processed in <see cref="DtpFactory.Receive" /></returns> public byte[] Receive(byte[] data, int start) { data = LZF.Decompress(data, start); var functionNameLength = BitConverter.ToInt32(data, 16); var functionName = Encoding.UTF8.GetString(data, 20, functionNameLength); if (!_procedures.ContainsKey(functionName) && !_functions.ContainsKey(functionName)) { ExceptionOccurred?.Invoke(this, new UnhandledExceptionEventArgs( new InvalidOperationException($"Method with name {functionName} not found"))); var errorResponse = new byte[16 + functionNameLength]; Array.Copy(DtpFactory.FunctionNotFoundExceptionGuid.ToByteArray(), errorResponse, 16); Array.Copy(data, 20, errorResponse, 16, functionNameLength); return(errorResponse); } var parameterCount = BitConverter.ToInt32(data, 20 + functionNameLength); var parameterLengths = new List <int>(); var parameters = new Dictionary <int, byte[]>(); for (int i = 0; i < parameterCount; i++) { parameterLengths.Add(BitConverter.ToInt32(data, 24 + functionNameLength + i * 4)); } var offset = 0; for (int i = 0; i < parameterCount; i++) { var parameterData = new byte[parameterLengths[i]]; Array.Copy(data, 24 + functionNameLength + parameterCount * 4 + offset, parameterData, 0, parameterData.Length); parameters.Add(i, parameterData); offset += parameterData.Length; } var dtpParameters = new DtpParameters(parameters); byte[] result = null; try { DtpProcedure procedure; if (_procedures.TryGetValue(functionName, out procedure)) { procedure.Invoke(dtpParameters); } else { DtpFunction function; if (_functions.TryGetValue(functionName, out function)) { var returnedObject = function.Invoke(dtpParameters); if (returnedObject != null) { var typeList = new List <Type> { returnedObject.GetType() }; Type[] specialTypes; if (_specialTypes.TryGetValue(functionName, out specialTypes)) { typeList.AddRange(specialTypes); } result = new Serializer(typeList).Serialize(returnedObject); } } } } catch (Exception ex) { var exception = new DtpException { Message = ex.Message, StackTrace = ex.StackTrace, FunctionName = functionName, ParameterInformation = string.Join(", ", parameters.Select(x => x.Key + " - " + x.Value.Length + " B").ToArray()), SessionGuid = new Guid(data.Take(16).ToArray()) }; var exceptionData = new Serializer(typeof(DtpException)).Serialize(exception); var errorResponse = new byte[16 + exceptionData.Length]; Array.Copy(DtpFactory.ExceptionGuid.ToByteArray(), errorResponse, 16); Array.Copy(exceptionData, 0, errorResponse, 16, exceptionData.Length); ExceptionOccurred?.Invoke(this, new UnhandledExceptionEventArgs(ex)); return(LZF.Compress(errorResponse, 0)); } var response = new byte[16 + 4 + (result?.Length ?? 0)]; //Protocol //HEAD - 16 Bytes - Guid //HEAD - 4 Bytes - Response Length //DATA - result.Length - Result Length Array.Copy(data, 0, response, 0, 16); //copy guid Array.Copy(BitConverter.GetBytes(result?.Length ?? 0), 0, response, 16, 4); if (result != null) { Array.Copy(result, 0, response, 20, result.Length); } return(LZF.Compress(response, 0)); }