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()) } }
// handleMessage is run in the coordinate goroutine. func (c *Conn) handleMessage(m rpccapnp.Message) { switch m.Which() { case rpccapnp.Message_Which_unimplemented: // no-op for now to avoid feedback loop case rpccapnp.Message_Which_abort: ma, err := m.Abort() if err != nil { log.Println("rpc: decode abort:", err) // Keep going, since we're trying to abort anyway. } a := Abort{ma} log.Print(a) c.manager.shutdown(a) case rpccapnp.Message_Which_return: if err := c.handleReturnMessage(m); err != nil { log.Println("rpc: handle return:", err) } case rpccapnp.Message_Which_finish: // TODO(light): what if answers never had this ID? // TODO(light): return if cancelled mfin, err := m.Finish() if err != nil { log.Println("rpc: decode finish:", err) return } id := answerID(mfin.QuestionId()) a := c.answers.pop(id) a.cancel() if mfin.ReleaseResultCaps() { c.exports.releaseList(a.resultCaps) } case rpccapnp.Message_Which_bootstrap: boot, err := m.Bootstrap() if err != nil { log.Println("rpc: decode bootstrap:", err) return } id := answerID(boot.QuestionId()) if err := c.handleBootstrapMessage(id); err != nil { log.Println("rpc: handle bootstrap:", err) } case rpccapnp.Message_Which_call: if err := c.handleCallMessage(m); err != nil { log.Println("rpc: handle call:", err) } case rpccapnp.Message_Which_release: rel, err := m.Release() if err != nil { log.Println("rpc: decode release:", err) return } id := exportID(rel.Id()) refs := int(rel.ReferenceCount()) c.exports.release(id, refs) case rpccapnp.Message_Which_disembargo: if err := c.handleDisembargoMessage(m); err != nil { // Any failure in a disembargo is a protocol violation. c.abort(err) } default: log.Printf("rpc: received unimplemented message, which = %v", m.Which()) um := newUnimplementedMessage(nil, m) c.sendMessage(um) } }