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());
            }
        }
Ejemplo n.º 2
0
        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}");
            }
        }
Ejemplo n.º 4
0
        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);
            }
        }