// handleCallMessage is run in the coordinate goroutine to handle a // received call message. It mutates the capability table of its // parameter. func (c *Conn) handleCallMessage(m rpccapnp.Message) error { mcall, err := m.Call() if err != nil { return err } mt, err := mcall.Target() if err != nil { return err } if mt.Which() != rpccapnp.MessageTarget_Which_importedCap && mt.Which() != rpccapnp.MessageTarget_Which_promisedAnswer { um := newUnimplementedMessage(nil, m) return c.sendMessage(um) } mparams, err := mcall.Params() if err != nil { return err } if err := c.populateMessageCapTable(mparams); err == errUnimplemented { um := newUnimplementedMessage(nil, m) return c.sendMessage(um) } else if err != nil { c.abort(err) return err } ctx, cancel := c.newContext() id := answerID(mcall.QuestionId()) a := c.answers.insert(id, cancel) if a == nil { // Question ID reused, error out. c.abort(errQuestionReused) return errQuestionReused } meth := capnp.Method{ InterfaceID: mcall.InterfaceId(), MethodID: mcall.MethodId(), } paramContent, err := mparams.Content() if err != nil { return err } cl := &capnp.Call{ Ctx: ctx, Method: meth, Params: capnp.ToStruct(paramContent), } if err := c.routeCallMessage(a, mt, cl); err != nil { msgs := a.reject(nil, err) for _, m := range msgs { if err := c.sendMessage(m); err != nil { return err } } return nil } return nil }
func formatMsg(w io.Writer, m rpccapnp.Message) { switch m.Which() { case rpccapnp.Message_Which_unimplemented: fmt.Fprint(w, "unimplemented") case rpccapnp.Message_Which_abort: mabort, _ := m.Abort() reason, _ := mabort.Reason() fmt.Fprintf(w, "abort type=%v: %s", mabort.Type(), reason) case rpccapnp.Message_Which_bootstrap: mboot, _ := m.Bootstrap() fmt.Fprintf(w, "bootstrap id=%d", mboot.QuestionId()) case rpccapnp.Message_Which_call: c, _ := m.Call() fmt.Fprintf(w, "call id=%d target=<", c.QuestionId()) tgt, _ := c.Target() formatMessageTarget(w, tgt) fmt.Fprintf(w, "> @%#x/@%d", c.InterfaceId(), c.MethodId()) case rpccapnp.Message_Which_return: r, _ := m.Return() fmt.Fprintf(w, "return id=%d", r.AnswerId()) if r.ReleaseParamCaps() { fmt.Fprint(w, " releaseParamCaps") } switch r.Which() { case rpccapnp.Return_Which_results: case rpccapnp.Return_Which_exception: exc, _ := r.Exception() reason, _ := exc.Reason() fmt.Fprintf(w, ", exception type=%v: %s", exc.Type(), reason) case rpccapnp.Return_Which_canceled: fmt.Fprint(w, ", canceled") case rpccapnp.Return_Which_resultsSentElsewhere: fmt.Fprint(w, ", results sent elsewhere") case rpccapnp.Return_Which_takeFromOtherQuestion: fmt.Fprint(w, ", results sent elsewhere") case rpccapnp.Return_Which_acceptFromThirdParty: fmt.Fprint(w, ", accept from third party") default: fmt.Fprintf(w, ", UNKNOWN RESULT which=%v", r.Which()) } case rpccapnp.Message_Which_finish: fin, _ := m.Finish() fmt.Fprintf(w, "finish id=%d", fin.QuestionId()) if fin.ReleaseResultCaps() { fmt.Fprint(w, " releaseResultCaps") } case rpccapnp.Message_Which_resolve: r, _ := m.Resolve() fmt.Fprintf(w, "resolve id=%d ", r.PromiseId()) switch r.Which() { case rpccapnp.Resolve_Which_cap: fmt.Fprint(w, "capability=") c, _ := r.Cap() formatCapDescriptor(w, c) case rpccapnp.Resolve_Which_exception: exc, _ := r.Exception() reason, _ := exc.Reason() fmt.Fprintf(w, "exception type=%v: %s", exc.Type(), reason) default: fmt.Fprintf(w, "UNKNOWN RESOLUTION which=%v", r.Which()) } case rpccapnp.Message_Which_release: rel, _ := m.Release() fmt.Fprintf(w, "release id=%d by %d", rel.Id(), rel.ReferenceCount()) case rpccapnp.Message_Which_disembargo: de, _ := m.Disembargo() tgt, _ := de.Target() fmt.Fprint(w, "disembargo <") formatMessageTarget(w, tgt) fmt.Fprint(w, "> ") dc := de.Context() switch dc.Which() { case rpccapnp.Disembargo_context_Which_senderLoopback: fmt.Fprintf(w, "sender loopback id=%d", dc.SenderLoopback()) case rpccapnp.Disembargo_context_Which_receiverLoopback: fmt.Fprintf(w, "receiver loopback id=%d", dc.ReceiverLoopback()) case rpccapnp.Disembargo_context_Which_accept: fmt.Fprint(w, "accept") case rpccapnp.Disembargo_context_Which_provide: fmt.Fprintf(w, "provide id=%d", dc.Provide()) default: fmt.Fprintf(w, "UNKNOWN CONTEXT which=%v", dc.Which()) } case rpccapnp.Message_Which_obsoleteSave: fmt.Fprint(w, "save") case rpccapnp.Message_Which_obsoleteDelete: fmt.Fprint(w, "delete") case rpccapnp.Message_Which_provide: prov, _ := m.Provide() tgt, _ := prov.Target() fmt.Fprintf(w, "provide id=%d <", prov.QuestionId()) formatMessageTarget(w, tgt) fmt.Fprint(w, ">") case rpccapnp.Message_Which_accept: acc, _ := m.Accept() fmt.Fprintf(w, "accept id=%d", acc.QuestionId()) if acc.Embargo() { fmt.Fprint(w, " with embargo") } case rpccapnp.Message_Which_join: join, _ := m.Join() tgt, _ := join.Target() fmt.Fprintf(w, "join id=%d <", join.QuestionId()) formatMessageTarget(w, tgt) fmt.Fprint(w, ">") default: fmt.Fprintf(w, "UNKNOWN MESSAGE which=%v", m.Which()) } }