Esempio n. 1
0
        protected virtual RpcMultiPartResponse MultiPartMessage(RpcMultiPartRequest request, ExtensionRegistry registry)
        {
            RpcSession session   = RpcCallContext.Session;
            string     messageId = request.TransactionId.ToBase64();
            Stream     message;

            if (!session.TryGetValue(messageId, out message))
            {
                if (request.CurrentPosition != 0)
                {
                    throw new InvalidDataException("The TransactionId is not valid.");
                }
                session.Add(messageId, message = CreateStream(request.TotalBytes));
                message.SetLength(request.TotalBytes);
            }
            if (request.MessageStatus == RpcMultiPartRequest.Types.RpcMessageStatus.CANCEL)
            {
                message.Dispose();
                session.Remove(messageId);
                return(RpcMultiPartResponse.CreateBuilder().SetContinue(false).Build());
            }
            if (message.Position != request.CurrentPosition || message.Length != request.TotalBytes ||
                request.BytesSent != request.PayloadBytes.Length)
            {
                throw new InvalidDataException();
            }
            request.PayloadBytes.WriteTo(message);

            if (request.MessageStatus == RpcMultiPartRequest.Types.RpcMessageStatus.COMPLETE)
            {
                using (message)
                {
                    session.Remove(messageId);
                    if (message.Position != request.TotalBytes)
                    {
                        throw new InvalidDataException();
                    }
                    message.Position = 0;
                    byte[] response =
                        next.CallMethod(request.MethodName, CodedInputStream.CreateInstance(message), registry).
                        ToByteArray();
                    return(RpcMultiPartResponse.CreateBuilder()
                           .SetResponseBytes(ByteString.CopyFrom(response))
                           .SetContinue(true)
                           .Build());
                }
            }
            return(RpcMultiPartResponse.CreateBuilder()
                   .SetContinue(true)
                   .Build());
        }
Esempio n. 2
0
        public void MultiPartMessageCancel()
        {
            //Notice that both client and server must enable multi-part messages...
            using (RpcServer.CreateRpc(iid, new SearchService.ServerStub(new AuthenticatedSearch()))
                   .AddAuthNegotiate()
                   .AddProtocol("ncacn_ip_tcp", "12345")
                   .EnableMultiPart()
                   .StartListening())
            {
                ByteString transaction = ByteString.CopyFrom(Guid.NewGuid().ToByteArray());
                using (
                    RpcClient client =
                        RpcClient.ConnectRpc(iid, "ncacn_ip_tcp", "::1", "12345").Authenticate(
                            RpcAuthenticationType.Self))
                {
                    RpcMultiPartResponse response = client.CallMethod(".multi",
                                                                      RpcMultiPartRequest.CreateBuilder()
                                                                      .SetTransactionId(transaction)
                                                                      .SetMessageStatus(
                                                                          RpcMultiPartRequest.Types.RpcMessageStatus
                                                                          .CONTINUE)
                                                                      .SetMethodName("Whatever")
                                                                      .SetCurrentPosition(0)
                                                                      .SetBytesSent(1000)
                                                                      .SetTotalBytes(2000)
                                                                      .SetPayloadBytes(
                                                                          ByteString.CopyFrom(new byte[1000]))
                                                                      .Build(),
                                                                      RpcMultiPartResponse.CreateBuilder());

                    Assert.IsTrue(response.Continue);

                    response = client.CallMethod(".multi",
                                                 RpcMultiPartRequest.CreateBuilder()
                                                 .SetTransactionId(transaction)
                                                 .SetMessageStatus(RpcMultiPartRequest.Types.RpcMessageStatus.CANCEL)
                                                 .Build(),
                                                 RpcMultiPartResponse.CreateBuilder());
                    Assert.IsFalse(response.Continue);
                }
            }
        }
Esempio n. 3
0
        TMessage IRpcDispatch.CallMethod <TMessage, TBuilder>(string method, IMessageLite request,
                                                              IBuilderLite <TMessage, TBuilder> response)
        {
            int size = request.SerializedSize;

            if (size < multiPartThreshold)
            {
                return(next.CallMethod(method, request, response));
            }
            else
            {
                ByteString transaction  = ByteString.CopyFrom(Guid.NewGuid().ToByteArray());
                byte[]     requestBytes = request.ToByteArray();

                RpcMultiPartRequest.Types.RpcMessageStatus status = RpcMultiPartRequest.Types.RpcMessageStatus.CONTINUE;
                try
                {
                    int total = requestBytes.Length;
                    int amt   = multiPartThreshold - 1024; //reserved for header
                    RpcMultiPartResponse mpr = RpcMultiPartResponse.DefaultInstance;

                    for (int pos = 0; pos < total; pos += amt)
                    {
                        amt    = Math.Min(amt, total - pos);
                        status = (pos + amt) < total ? status : RpcMultiPartRequest.Types.RpcMessageStatus.COMPLETE;
                        mpr    = next.CallMethod(".multi",
                                                 RpcMultiPartRequest.CreateBuilder()
                                                 .SetTransactionId(transaction)
                                                 .SetMethodName(method)
                                                 .SetMessageStatus(status)
                                                 .SetCurrentPosition(pos)
                                                 .SetTotalBytes(total)
                                                 .SetBytesSent(amt)
                                                 .SetPayloadBytes(ByteString.CopyFrom(requestBytes, pos, amt))
                                                 .Build(),
                                                 RpcMultiPartResponse.CreateBuilder()
                                                 );
                        if (!mpr.Continue)
                        {
                            throw new InvalidDataException("The operation was canceled by the server.");
                        }
                    }
                    if (!mpr.HasResponseBytes)
                    {
                        throw new InvalidDataException("The server did not provide a response.");
                    }

                    return(response.MergeFrom(mpr.ResponseBytes.ToByteArray(), extensions).Build());
                }
                catch
                {
                    if (status == RpcMultiPartRequest.Types.RpcMessageStatus.CONTINUE)
                    {
                        try
                        {
                            next.CallMethod(".multi",
                                            RpcMultiPartRequest.CreateBuilder()
                                            .SetTransactionId(transaction)
                                            .SetMessageStatus(RpcMultiPartRequest.Types.RpcMessageStatus.CANCEL)
                                            .Build(),
                                            RpcVoid.CreateBuilder()
                                            );
                        }
                        catch (Exception e)
                        {
                            Trace.TraceWarning("Unable to cancel multi-part message: {0}, error = {1}", transaction, e);
                        }
                    }
                    throw;
                }
            }
        }