// populateMessageCapTable converts the descriptors in the payload into // clients and sets it on the message the payload is a part of. func (c *Conn) populateMessageCapTable(payload rpccapnp.Payload) error { msg := payload.Segment().Message() ctab, err := payload.CapTable() if err != nil { return err } for i, n := 0, ctab.Len(); i < n; i++ { desc := ctab.At(i) switch desc.Which() { case rpccapnp.CapDescriptor_Which_none: msg.AddCap(nil) case rpccapnp.CapDescriptor_Which_senderHosted: id := importID(desc.SenderHosted()) client := c.addImport(id) msg.AddCap(client) case rpccapnp.CapDescriptor_Which_senderPromise: // We do the same thing as senderHosted, above. @kentonv suggested this on // issue #2; this let's messages be delivered properly, although it's a bit // of a hack, and as Kenton describes, it has some disadvantages: // // > * Apps sometimes want to wait for promise resolution, and to find out if // > it resolved to an exception. You won't be able to provide that API. But, // > usually, it isn't needed. // > * If the promise resolves to a capability hosted on the receiver, // > messages sent to it will uselessly round-trip over the network // > rather than being delivered locally. id := importID(desc.SenderPromise()) client := c.addImport(id) msg.AddCap(client) case rpccapnp.CapDescriptor_Which_receiverHosted: id := exportID(desc.ReceiverHosted()) e := c.findExport(id) if e == nil { return fmt.Errorf("rpc: capability table references unknown export ID %d", id) } msg.AddCap(e.rc.Ref()) case rpccapnp.CapDescriptor_Which_receiverAnswer: recvAns, err := desc.ReceiverAnswer() if err != nil { return err } id := answerID(recvAns.QuestionId()) a := c.answers[id] if a == nil { return fmt.Errorf("rpc: capability table references unknown answer ID %d", id) } recvTransform, err := recvAns.Transform() if err != nil { return err } transform := promisedAnswerOpsToTransform(recvTransform) msg.AddCap(a.pipelineClient(transform)) default: c.errorf("unknown capability type %v", desc.Which()) return errUnimplemented } } return nil }
func (c *Conn) fillParams(payload rpccapnp.Payload, cl *capnp.Call) error { params, err := cl.PlaceParams(payload.Segment()) if err != nil { return err } if err := payload.SetContent(params); err != nil { return err } ctab, err := c.makeCapTable(payload.Segment()) if err != nil { return err } if err := payload.SetCapTable(ctab); err != nil { return err } return nil }