コード例 #1
0
        public async Task WriteAsync(CapnpNet.Message msg)
        {
            await _semaphore.WaitAsync();

            try
            {
                await msg.SerializeAsync(_writeStream);
            }
            finally
            {
                _semaphore.Release();
            }

            msg.Dispose();
        }
コード例 #2
0
        public async Task <CapnpNet.Message> ReceiveAsync()
        {
            var msg    = new CapnpNet.Message().Init(null, false);
            var intBuf = ArrayPool <byte> .Shared.Rent(16);

            var bytesRead = await _readStream.ReadAsync(intBuf, 0, 4);

            if (bytesRead < intBuf.Length)
            {
                throw new InvalidOperationException("Expected more data");
            }

            var segmentCount = BitConverter.ToInt32(intBuf, 0) + 1;
            var readLen      = segmentCount * 4 + (segmentCount % 2 == 0 ? 4 : 0);

            if (intBuf.Length < readLen)
            {
                ArrayPool <byte> .Shared.Return(intBuf);

                intBuf = ArrayPool <byte> .Shared.Rent(segmentCount * 4 + 4);
            }

            bytesRead = await _readStream.ReadAsync(intBuf, 0, readLen);

            if (bytesRead < intBuf.Length)
            {
                throw new InvalidOperationException("Expected more data");
            }

            for (int i = 0; i < segmentCount; i++)
            {
                var len = BitConverter.ToInt32(intBuf, i * 4) * 8;
                var seg = await _segFactory.CreateAsync(msg, len);

                seg.Is(out ArraySegment <byte> arrSeg);
                bytesRead = await _readStream.ReadAsync(arrSeg.Array, arrSeg.Offset, len);

                if (bytesRead < len)
                {
                    throw new InvalidOperationException("Expected more data");
                }
            }

            ArrayPool <byte> .Shared.Return(intBuf);

            return(msg);
        }
コード例 #3
0
        internal void Process(CapnpNet.Message rpcMessage)
        {
            try
            {
                var message = rpcMessage.GetRoot <Message>();
                if (message.Is(out Message unimplemented))
                {
                    // TODO: release resources
                    throw new NotImplementedException();
                }
                else if (message.Is(out Exception abort))
                {
                    throw new InvalidOperationException($"Connection aborted by remote: {abort.type.ToString()}: {abort.reason.ToString()}");
                }
                else if (message.Is(out Bootstrap bootstrap))
                {
                    var reply = new CapnpNet.Message().Init(_segFactory, true);
                    //await reply.PreAllocateAsync(senderMsg.CalculateSize() + 3);
                    reply.SetRoot(new Return(reply)
                    {
                        answerId = bootstrap.questionId,
                        which    = Return.Union.results,
                        results  = new Payload
                        {
                            content = new OtherPointer
                            {
                                Type             = PointerType.Other,
                                OtherPointerType = OtherPointerType.Capability,
                                CapabilityId     = 0
                            },
                            capTable = new FlatArray <CapDescriptor>(reply, 1, out AllocationContext allocContext)
                            {
                                new CapDescriptor(ref allocContext)
                                {
                                    which        = CapDescriptor.Union.senderHosted,
                                    senderHosted = this.ExportCap(_bootstrapCap)
                                }
                            }
                        }
                    });
                    rpcMessage.Dispose();
                    rpcMessage = null;
                    this.Consume((msgStream: _msgStream, reply: reply), async state =>
                    {
                        await state.msgStream.WriteAsync(state.reply);
                        state.reply.Dispose();
                    });
                }
                else if (message.Is(out Call call))
                {
                    bool       valid;
                    ref Answer ans = ref _answers.TryGet(call.questionId, out valid);
                    if (!valid)
                    {
                        // TODO: return exception message
                    }

                    if (call.target.which == MessageTarget.Union.importedCap)
                    {
                        ref Export export = ref _exports.TryGet(call.target.importedCap, out valid);
                        if (!valid)
                        {
                            // TODO: return exception message
                        }

                        // TODO: read cap descriptors, look up corresponding imports, await any still pending

                        if ([email protected](out var @struct) == false)
                        {
                            // TODO: return exception
                        }

                        switch (call.sendResultsTo.which)
                        {
                        case Call.sendResultsToGroup.Union.caller:
                            // set up return message
                            break;

                        case Call.sendResultsToGroup.Union.yourself:
                            // set aside memory to hold result
                            break;

                        case Call.sendResultsToGroup.Union.thirdParty:
                        default:
                            throw new NotImplementedException();
                        }

                        //ans.task = export.capability.DispatchCall(
                        //  call.interfaceId,
                        //  call.methodId,
                        //  new CallContext(call, this),
                        //  CancellationToken.None);

                        var callTask = ans.task;
                        this.Consume(async() =>
                        {
                            await callTask;
                            if (call.sendResultsTo.which == Call.sendResultsToGroup.Union.caller)
                            {
                            }
                        });
                    }