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()) } }
// handleReturnMessage is run in the coordinate goroutine. func (c *Conn) handleReturnMessage(m rpccapnp.Message) error { ret, err := m.Return() if err != nil { return err } id := questionID(ret.AnswerId()) q := c.questions.pop(id) if q == nil { return fmt.Errorf("received return for unknown question id=%d", id) } if ret.ReleaseParamCaps() { c.exports.releaseList(q.paramCaps) } if _, _, _, resolved := q.peek(); resolved { // If the question was already resolved, that means it was canceled, // in which case we already sent the finish message. return nil } releaseResultCaps := true switch ret.Which() { case rpccapnp.Return_Which_results: releaseResultCaps = false results, err := ret.Results() if err != nil { return err } if err := c.populateMessageCapTable(results); err == errUnimplemented { um := newUnimplementedMessage(nil, m) c.sendMessage(um) return errUnimplemented } else if err != nil { c.abort(err) return err } content, err := results.Content() if err != nil { return err } disembargoes := q.fulfill(content, c.embargoes.new) for _, d := range disembargoes { if err := c.sendMessage(d); err != nil { // shutdown return nil } } case rpccapnp.Return_Which_exception: exc, err := ret.Exception() if err != nil { return err } e := error(Exception{exc}) if q.method != nil { e = &capnp.MethodError{ Method: q.method, Err: e, } } else { e = bootstrapError{e} } q.reject(questionResolved, e) case rpccapnp.Return_Which_canceled: err := &questionError{ id: id, method: q.method, err: fmt.Errorf("receiver reported canceled"), } log.Println(err) q.reject(questionResolved, err) return nil default: um := newUnimplementedMessage(nil, m) c.sendMessage(um) return errUnimplemented } fin := newFinishMessage(nil, id, releaseResultCaps) c.sendMessage(fin) return nil }