Created
August 5, 2019 03:27
-
-
Save Vaelatern/dd8aae465e3807af5d189143377f5008 to your computer and use it in GitHub Desktop.
Minimum broken example for websockets.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Code generated by capnpc-go. DO NOT EDIT. | |
// Not relevant to this example. Just minimum necessary code. | |
package spec | |
import ( | |
context "golang.org/x/net/context" | |
capnp "zombiezen.com/go/capnproto2" | |
text "zombiezen.com/go/capnproto2/encoding/text" | |
schemas "zombiezen.com/go/capnproto2/schemas" | |
server "zombiezen.com/go/capnproto2/server" | |
) | |
type R struct{ Client capnp.Client } | |
// R_TypeID is the unique identifier for the type R. | |
const R_TypeID = 0x92cb9960ce88a13d | |
func (c R) Note(ctx context.Context, params func(R_note_Params) error, opts ...capnp.CallOption) R_note_Results_Promise { | |
if c.Client == nil { | |
return R_note_Results_Promise{Pipeline: capnp.NewPipeline(capnp.ErrorAnswer(capnp.ErrNullClient))} | |
} | |
call := &capnp.Call{ | |
Ctx: ctx, | |
Method: capnp.Method{ | |
InterfaceID: 0x92cb9960ce88a13d, | |
MethodID: 0, | |
InterfaceName: "basic.capnp:R", | |
MethodName: "note", | |
}, | |
Options: capnp.NewCallOptions(opts), | |
} | |
if params != nil { | |
call.ParamsSize = capnp.ObjectSize{DataSize: 8, PointerCount: 0} | |
call.ParamsFunc = func(s capnp.Struct) error { return params(R_note_Params{Struct: s}) } | |
} | |
return R_note_Results_Promise{Pipeline: capnp.NewPipeline(c.Client.Call(call))} | |
} | |
type R_Server interface { | |
Note(R_note) error | |
} | |
func R_ServerToClient(s R_Server) R { | |
c, _ := s.(server.Closer) | |
return R{Client: server.New(R_Methods(nil, s), c)} | |
} | |
func R_Methods(methods []server.Method, s R_Server) []server.Method { | |
if cap(methods) == 0 { | |
methods = make([]server.Method, 0, 1) | |
} | |
methods = append(methods, server.Method{ | |
Method: capnp.Method{ | |
InterfaceID: 0x92cb9960ce88a13d, | |
MethodID: 0, | |
InterfaceName: "basic.capnp:R", | |
MethodName: "note", | |
}, | |
Impl: func(c context.Context, opts capnp.CallOptions, p, r capnp.Struct) error { | |
call := R_note{c, opts, R_note_Params{Struct: p}, R_note_Results{Struct: r}} | |
return s.Note(call) | |
}, | |
ResultsSize: capnp.ObjectSize{DataSize: 0, PointerCount: 0}, | |
}) | |
return methods | |
} | |
// R_note holds the arguments for a server call to R.note. | |
type R_note struct { | |
Ctx context.Context | |
Options capnp.CallOptions | |
Params R_note_Params | |
Results R_note_Results | |
} | |
type R_note_Params struct{ capnp.Struct } | |
// R_note_Params_TypeID is the unique identifier for the type R_note_Params. | |
const R_note_Params_TypeID = 0xbfba254722426321 | |
func NewR_note_Params(s *capnp.Segment) (R_note_Params, error) { | |
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) | |
return R_note_Params{st}, err | |
} | |
func NewRootR_note_Params(s *capnp.Segment) (R_note_Params, error) { | |
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}) | |
return R_note_Params{st}, err | |
} | |
func ReadRootR_note_Params(msg *capnp.Message) (R_note_Params, error) { | |
root, err := msg.RootPtr() | |
return R_note_Params{root.Struct()}, err | |
} | |
func (s R_note_Params) String() string { | |
str, _ := text.Marshal(0xbfba254722426321, s.Struct) | |
return str | |
} | |
func (s R_note_Params) R() bool { | |
return s.Struct.Bit(0) | |
} | |
func (s R_note_Params) SetR(v bool) { | |
s.Struct.SetBit(0, v) | |
} | |
// R_note_Params_List is a list of R_note_Params. | |
type R_note_Params_List struct{ capnp.List } | |
// NewR_note_Params creates a new list of R_note_Params. | |
func NewR_note_Params_List(s *capnp.Segment, sz int32) (R_note_Params_List, error) { | |
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 0}, sz) | |
return R_note_Params_List{l}, err | |
} | |
func (s R_note_Params_List) At(i int) R_note_Params { return R_note_Params{s.List.Struct(i)} } | |
func (s R_note_Params_List) Set(i int, v R_note_Params) error { return s.List.SetStruct(i, v.Struct) } | |
func (s R_note_Params_List) String() string { | |
str, _ := text.MarshalList(0xbfba254722426321, s.List) | |
return str | |
} | |
// R_note_Params_Promise is a wrapper for a R_note_Params promised by a client call. | |
type R_note_Params_Promise struct{ *capnp.Pipeline } | |
func (p R_note_Params_Promise) Struct() (R_note_Params, error) { | |
s, err := p.Pipeline.Struct() | |
return R_note_Params{s}, err | |
} | |
type R_note_Results struct{ capnp.Struct } | |
// R_note_Results_TypeID is the unique identifier for the type R_note_Results. | |
const R_note_Results_TypeID = 0xeada765e4955823d | |
func NewR_note_Results(s *capnp.Segment) (R_note_Results, error) { | |
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) | |
return R_note_Results{st}, err | |
} | |
func NewRootR_note_Results(s *capnp.Segment) (R_note_Results, error) { | |
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}) | |
return R_note_Results{st}, err | |
} | |
func ReadRootR_note_Results(msg *capnp.Message) (R_note_Results, error) { | |
root, err := msg.RootPtr() | |
return R_note_Results{root.Struct()}, err | |
} | |
func (s R_note_Results) String() string { | |
str, _ := text.Marshal(0xeada765e4955823d, s.Struct) | |
return str | |
} | |
// R_note_Results_List is a list of R_note_Results. | |
type R_note_Results_List struct{ capnp.List } | |
// NewR_note_Results creates a new list of R_note_Results. | |
func NewR_note_Results_List(s *capnp.Segment, sz int32) (R_note_Results_List, error) { | |
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 0}, sz) | |
return R_note_Results_List{l}, err | |
} | |
func (s R_note_Results_List) At(i int) R_note_Results { return R_note_Results{s.List.Struct(i)} } | |
func (s R_note_Results_List) Set(i int, v R_note_Results) error { return s.List.SetStruct(i, v.Struct) } | |
func (s R_note_Results_List) String() string { | |
str, _ := text.MarshalList(0xeada765e4955823d, s.List) | |
return str | |
} | |
// R_note_Results_Promise is a wrapper for a R_note_Results promised by a client call. | |
type R_note_Results_Promise struct{ *capnp.Pipeline } | |
func (p R_note_Results_Promise) Struct() (R_note_Results, error) { | |
s, err := p.Pipeline.Struct() | |
return R_note_Results{s}, err | |
} | |
const schema_902d2bfc3bbf0d49 = "x\xda\x12\xa8p`2d\xcdgb`\x08\x94ae" + | |
"\xfbo\xbb\xb0\xe3\\\xc2\xcc\xd3\x93\x18\x04y\x98\xff{" + | |
"\xf2\xee\xb7\xfe\xa3\xad;\x81\x81\x81QX\x96\xb1HX" + | |
"\x91\x91\x9d\x81AX\x96\xd1]\xd8\x15\xc4\xfa\xaf\x98\xec" + | |
"\xa4\xe4\xae\xbak?C \x1f##\x03\x03\x0bHV" + | |
"\x97\xf1\x12\x03\xa3\xb0!\xa3=\x03\xe3\x7f\xdb\xa6P\xcf" + | |
"\xb8\xb2[\xaf\x18\x04\xf9`\xd2\x81\x8c\xb7\x18\x0c\xfe'" + | |
"%\x16g&\xeb%'2\xc8\x17\xe4\x15X\x05\x050" + | |
"2\x06\xb20\xb3\"\x99\xc8\x08\xd3*(\xa8\xc5\xc0$" + | |
"\xc8\xca\xce\x9f\x97_\x92\xea\xc0\x18\xc0\xc8\x08\xd7\xcc\x04" + | |
"\xd6\xab\x07\x92P\x09H,J\xcce,\x0edaf" + | |
"a``ad`\x10\xe4\x15b`\x08\xe4`f\x0c" + | |
"\x14abd,bdd`bdd\xc0\xae9(" + | |
"\xb5\xb84\x87\xb9\xa4\x18\x10\x00\x00\xff\xff\x02bA\xd5" | |
func init() { | |
schemas.Register(schema_902d2bfc3bbf0d49, | |
0x92cb9960ce88a13d, | |
0xbfba254722426321, | |
0xeada765e4955823d) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//go:generate capnp compile -ogo:api -I ./capnp basic.capnp | |
package main | |
import ( | |
"context" | |
"log" | |
"net/http" | |
"nhooyr.io/websocket" | |
"zombiezen.com/go/capnproto2/rpc" | |
"github.com/dxpb/dxpb/api" | |
) | |
type r struct { | |
*r_actual | |
} | |
type r_actual struct{} | |
func (b *r_actual) Note(call spec.R_note) error { | |
return nil | |
} | |
func connectDrone(url string) spec.R_note_Results { | |
ctx := context.Background() | |
rawconn, _, err := websocket.Dial(ctx, url, websocket.DialOptions{ | |
Subprotocols: []string{"proto"}, | |
}) | |
if err != nil { | |
log.Fatal("TODO: Don't fatally crash on failed dials: err: ", err) | |
} | |
conn := rpc.NewConn(rpc.StreamTransport(websocket.NetConn(rawconn))) | |
log.Println("About to trigger crash") | |
drone := spec.R{Client: conn.Bootstrap(ctx)} | |
log.Println("Passed the crash begin. If there were a sleep, it'd already have errored.") | |
rV, err := drone.Note(ctx, func(p spec.R_note_Params) error { | |
return nil | |
}).Struct() | |
log.Println("Now done with the RPC call, but I bet it errored...") | |
if err != nil { | |
log.Fatal("TODO: Don't fatally crash when the call fails due to err: ", err) | |
} | |
return rV | |
} | |
func ListenAndWork(listen string) { | |
var actee r | |
http.HandleFunc("/v1/ws", func(w http.ResponseWriter, r *http.Request) { | |
conn, err := websocket.Accept(w, r, websocket.AcceptOptions{ | |
Subprotocols: []string{"proto"}, | |
}) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
defer conn.Close(websocket.StatusInternalError, "the sky is falling") | |
transport := rpc.StreamTransport(websocket.NetConn(conn)) | |
iface := rpc.MainInterface(spec.R_ServerToClient(actee).Client) | |
rpcconn := rpc.NewConn(transport, iface) | |
rpcconn.Wait() | |
}) | |
log.Println("Now listening on " + listen) | |
log.Fatal(http.ListenAndServe(listen, nil)) | |
} | |
func main() { | |
go ListenAndWork("localhost:9191") | |
connectDrone("ws://localhost:9191/v1/ws") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment