internal void Send(uint responseId, ServiceProtocolResponse response) { var newValue = Interlocked.Increment(ref responsesQueueSize); Thread.MemoryBarrier(); responsesQueue.Enqueue(new Response { id = responseId, response = response }); if (newValue == 1) { Task.Run(() => SendResponse()); } }
public void SendResponse(ServiceProtocolResponse response) { if (response == null) { throw new ArgumentNullException(nameof(response)); } if (connection == null) { throw new InvalidOperationException("Access denied!"); } if (id == ServiceProtocolDataContract.RequestIdWithoutResponse) { throw new InvalidOperationException("This request is not associated with any response!"); } connection.Send(id, response); connection = null; }
private void SendResponse() { try { currentResponsesCount = 0; packStream.Position = 0; while (true) { var lastPos = (int)packStream.Position; var response = GetNextResponse(currentResponsesCount == 0); if (response.response == null) { break; } packStream.Position += ServiceProtocolResponse.HeaderSize; var startPos = (int)packStream.Position; byte kind = 0; if (response.response.Code == ServiceProtocolResponseCode.Success) { if (!server.dataContract.responsePackers.TryGetValue(response.response.GetType(), out var packerInfo)) { server.logger.Fatal($"Service protocol server: Could not find response packer by type: {response.response.GetType()}"); packStream.Position = lastPos; goto AfterResponsePackError; } kind = packerInfo.kind; try { packerInfo.packer(packWriter, response.response); } catch (Exception e) { server.logger.Fatal($"Service protocol server: Could not pack response! Type: {response.response.GetType()} Details: {e}"); packStream.Position = lastPos; goto AfterResponsePackError; } } var endPos = (int)packStream.Position; var responseSize = endPos - startPos; if (responseSize > ServiceProtocolResponse.MaxSize) { server.logger.Fatal( $"Service protocol server: Could not send response! Response length exceeds allowed size! Type: {response.response.GetType()} Size: {responseSize} Max size: {ServiceProtocolResponse.MaxSize}"); packStream.Position = lastPos; goto AfterResponsePackError; } ServiceProtocolResponse.WriteHeader(sendArgs.Buffer, lastPos, response.id, kind, response.response.Code, (ushort)responseSize); AfterResponsePackError: currentResponsesCount++; if (packStream.Position >= server.dataContract.responseBufferSize) { break; } } Thread.MemoryBarrier(); sendArgs.SetBuffer(0, (int)packStream.Position); if (!socket.SendAsync(sendArgs)) { SendingComplete(null, sendArgs); } } catch (Exception e) when(e is ObjectDisposedException || e is SocketException || e is NotSupportedException) { } catch (Exception e) { server.logger.Fatal($"Service protocol server: Internal error! Details: {e}"); } }
private void Receive(object sender, SocketAsyncEventArgs args) { if (args.BytesTransferred == 0 || args.SocketError != SocketError.Success) { if (args.SocketError != SocketError.Success) { logger.Error($"Service protocol client {id}: Connection closed! Reason: {args.SocketError}"); } DisconnectLogic(); return; } lastConnectionActiveTime = Environment.TickCount; var bytesAvailable = args.Offset + args.BytesTransferred; var offset = 0; while (true) { if (bytesAvailable < ServiceProtocolResponse.HeaderSize) { goto ContinueReceive; } ServiceProtocolResponse.ReadHeader(args.Buffer, offset, out var responseId, out var responseKind, out var responseCode, out var responseSize); if (bytesAvailable - ServiceProtocolResponse.HeaderSize < responseSize) { goto ContinueReceive; } offset += ServiceProtocolResponse.HeaderSize; bytesAvailable -= ServiceProtocolResponse.HeaderSize; unpackStream.Position = offset; if (responseCode == ServiceProtocolResponseCode.Success) { if (responseKind >= dataContract.responseUnpackers.Length) { logger.Error($"Service protocol client {id}: Received invalid response kind!"); DisconnectLogic(); return; } var unpacker = dataContract.responseUnpackers[responseKind]; if (unpacker == null) { logger.Error($"Service protocol client {id}: Could not find response unpacker by kind {responseKind}!"); DisconnectLogic(); return; } ServiceProtocolResponse response; try { response = unpacker(unpackReader); } catch (Exception e) { logger.Fatal($"Service protocol client {id}: Could not unpack response! Kind: {responseKind} Details: {e}"); DisconnectLogic(); return; } var realUnpackedSize = (int)(unpackStream.Position - offset); if (realUnpackedSize != responseSize) { logger.Error($"Service protocol client {id}: Could not unpack response! Kind: {responseKind} Real unpacked size not equal with size in header!"); DisconnectLogic(); return; } bytesAvailable -= responseSize; offset += responseSize; ServiceProtocolResponse.localThreadResponse = response; } GetContinuation: var continuation = requestContinuations[responseId]; if (continuation == null) { Thread.SpinWait(1); goto GetContinuation; } Thread.MemoryBarrier(); while (Interlocked.CompareExchange(ref requestStates[responseId], RequestStateInactive, RequestStateAfterSend) != RequestStateAfterSend) { } Thread.MemoryBarrier(); requestContinuations[responseId] = null; Thread.MemoryBarrier(); ServiceProtocolResponse.localThreadCodeForErrorResponses = responseCode; try { continuation(); } catch (Exception e) { logger.Fatal($"Service protocol client {id}: Could not process request continuation! Details: {e}"); } if (bytesAvailable == 0) { goto ContinueReceive; } } ContinueReceive: if (bytesAvailable > 0) { Array.Copy(args.Buffer, offset, args.Buffer, 0, bytesAvailable); } args.SetBuffer(bytesAvailable, args.Buffer.Length - bytesAvailable); if (!socket.ReceiveAsync(args)) { Receive(null, args); } }