/// <summary> /// Called when the server receives an unserialized request. /// </summary> /// <param name="requestBytes">The serialized request.</param> private void OnRequest(byte[] requestBytes) { try { using (var input = new EnhancedMemoryStream(requestBytes)) { int typeCode = input.ReadInt32(); SharedMemMessage request; SharedMemMessage response; if (typeCode < 0) { request = new SharedMemErrorMessage(); } else { request = messageFactory.Create(typeCode); } request.InternalReadFrom(input); request.ReadFrom(input); try { response = requestHandler(request); if (response == null) { throw new NullReferenceException("Server request handler returned a NULL response message."); } } catch (Exception e) { response = new SharedMemErrorMessage(); response.InternalError = string.Format("{0}: {1}", e.GetType().FullName, e.Message); } response.InternalRequestId = request.InternalRequestId; response.InternalClientInbox = request.InternalClientInbox; using (var output = new EnhancedMemoryStream(response.SerializedCapacityHint)) { output.WriteInt32(response.TypeCode); response.InternalWriteTo(output); response.WriteTo(output); // This call is synchronous but should execute very quickly (microseconds). outbox.Send(response.InternalClientInbox, output.ToArray()); } } } catch (Exception e) { SysLog.LogException(e); } }
/// <summary> /// Asynchronously submits a <see cref="SharedMemMessage"/> request message to the server /// and waits for and returns the response <see cref="SharedMemMessage"/>. /// </summary> /// <param name="request">The request message.</param> /// <param name="timeout">The optional timeout to override the <see cref="Timeout"/> property. /// </param> /// <returns>The response <see cref="SharedMemMessage"/>.</returns> public Task <SharedMemMessage> CallAsync(SharedMemMessage request, TimeSpan?timeout = null) { if (request == null) { throw new ArgumentNullException("request"); } if (request.InternalRequestId != Guid.Empty) { throw new InvalidOperationException("Cannot reuse a [SharedMemMessage] request instance previously submitted for a call operation."); } request.InternalRequestId = Guid.NewGuid(); request.InternalClientInbox = this.ClientName; if (!timeout.HasValue) { timeout = this.Timeout; } var operation = new PendingOperation(request, new TaskCompletionSource <SharedMemMessage>(), stopwatch.Elapsed + timeout.Value); lock (syncLock) { pendingOperations.Add(request.InternalRequestId, operation); } try { using (var output = new EnhancedMemoryStream(request.SerializedCapacityHint)) { output.WriteInt32(request.TypeCode); request.InternalWriteTo(output); request.WriteTo(output); // This call is synchronous but should execute very quickly (microseconds). outbox.Send(ServerName, output.ToArray()); } } catch (Exception e) { lock (syncLock) { pendingOperations.Remove(operation.RequestMessage.InternalRequestId); } operation.Tcs.TrySetException(e); } return(operation.Tcs.Task); }