diff --git a/examples/README.md b/examples/README.md index ce23bf5..1fc53a5 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,4 +5,5 @@ The following examples are in this directory: * [simpleclient](simpleclient) - A simple Tor client for connecting to the web or other onion services * [simpleserver](simpleserver) - Hosting simple "hello world" Tor onion service * [embeddedversion](embeddedversion) - Example showing how to dump the version of Tor embedded in the binary -* [embeddedfileserver](embeddedfileserver) - Example showing a file server using Tor embedded in the binary \ No newline at end of file +* [embeddedfileserver](embeddedfileserver) - Example showing a file server using Tor embedded in the binary +* [grpc](grpc) - Example showing how to use gRPC over Tor \ No newline at end of file diff --git a/examples/grpc/main.go b/examples/grpc/main.go new file mode 100644 index 0000000..d022999 --- /dev/null +++ b/examples/grpc/main.go @@ -0,0 +1,218 @@ +package main + +import ( + "context" + "fmt" + "io" + "log" + "net" + "reflect" + "strings" + "time" + + "github.com/cretz/bine/examples/grpc/pb" + "github.com/cretz/bine/tor" + "google.golang.org/grpc" +) + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} + +func run() error { + log.Printf("Starting Tor") + // We'll give it 5 minutes to run the whole thing (way too much of course, usually about 20 seconds) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + t, err := tor.Start(ctx, nil) + if err != nil { + return err + } + defer t.Close() + + log.Printf("Starting onion service, please wait") + server, onionID, err := startServer(ctx, t) + if err != nil { + return err + } + defer server.Stop() + log.Printf("Onion service available at %v.onion", onionID) + + log.Printf("Connecting to onion service") + conn, client, err := startClient(ctx, t, onionID+".onion:80") + if err != nil { + return err + } + defer conn.Close() + + log.Printf("Doing simple RPC") + resp, err := client.JoinStrings(ctx, &pb.JoinStringsRequest{Strings: []string{"foo", "bar", "baz"}, Delimiter: "-"}) + if err != nil { + return err + } else if resp.Joined != "foo-bar-baz" { + return fmt.Errorf("Invalid response: %v", resp.Joined) + } + + log.Printf("Doing server-side streaming RPC") + pStream, err := client.ProvideStrings(ctx, &pb.ProvideStringsRequest{Count: 10}) + if err != nil { + return err + } + for i := 0; i < 10; i++ { + if resp, err := pStream.Recv(); err != nil { + return err + } else if resp.String_ != fmt.Sprintf("string-%v", i+1) { + return fmt.Errorf("Invalid response: %v", resp.String_) + } + } + if _, err = pStream.Recv(); err != io.EOF { + return fmt.Errorf("Expected EOF, got %v", err) + } + + log.Printf("Doing client-side streaming RPC") + rStream, err := client.ReceiveStrings(ctx) + strs := []string{"foo", "bar", "baz"} + for _, str := range strs { + if err := rStream.Send(&pb.ReceiveStringsRequest{String_: str}); err != nil { + return err + } + } + if resp, err := rStream.CloseAndRecv(); err != nil { + return err + } else if !reflect.DeepEqual(resp.Received, strs) { + return fmt.Errorf("Unexpected response: %v", resp.Received) + } + + log.Printf("Doing bi-directional streaming RPC") + eStream, err := client.ExchangeStrings(ctx) + for _, str := range strs { + if err := eStream.Send(&pb.ExchangeStringsRequest{String_: str, WantReturn: str == "baz"}); err != nil { + return err + } + } + if resp, err := eStream.Recv(); err != nil { + return err + } else if !reflect.DeepEqual(resp.Received, strs) { + return fmt.Errorf("Unexpected response: %v", resp.Received) + } + err = eStream.Send(&pb.ExchangeStringsRequest{String_: "one"}) + if err == nil { + err = eStream.Send(&pb.ExchangeStringsRequest{String_: "two", WantReturn: true}) + } + if err == nil { + err = eStream.CloseSend() + } + if err != nil { + return err + } + if resp, err := eStream.Recv(); err != nil { + return err + } else if !reflect.DeepEqual(resp.Received, []string{"one", "two"}) { + return fmt.Errorf("Unexpected response: %v", resp.Received) + } + if _, err = eStream.Recv(); err != io.EOF { + return fmt.Errorf("Expected EOF, got %v", err) + } + + log.Printf("All completed successfully, shutting down") + return nil +} + +func startServer(ctx context.Context, t *tor.Tor) (server *grpc.Server, onionID string, err error) { + // Wait at most a few minutes to publish the service + listenCtx, listenCancel := context.WithTimeout(ctx, 3*time.Minute) + defer listenCancel() + // Create an onion service to listen on a random local port but show as 80 + // We'll do version 3 since it's quicker + onion, err := t.Listen(listenCtx, &tor.ListenConf{Version3: true, RemotePorts: []int{80}}) + if err != nil { + return nil, "", err + } + onionID = onion.ID + // Create the grpc server and start it + server = grpc.NewServer() + pb.RegisterSimpleServiceServer(server, simpleService{}) + go func() { + if err := server.Serve(onion); err != nil { + log.Printf("Error serving: %v", err) + } + }() + return +} + +func startClient( + ctx context.Context, t *tor.Tor, addr string, +) (conn *grpc.ClientConn, client pb.SimpleServiceClient, err error) { + // Wait at most a few minutes to connect to the service + connCtx, connCancel := context.WithTimeout(ctx, 3*time.Minute) + defer connCancel() + // Make the dialer + dialer, err := t.Dialer(connCtx, nil) + if err != nil { + return nil, nil, err + } + // Make the connection + conn, err = grpc.DialContext(connCtx, addr, + grpc.FailOnNonTempDialError(true), + grpc.WithBlock(), + grpc.WithInsecure(), + grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { + dialCtx, dialCancel := context.WithTimeout(ctx, timeout) + defer dialCancel() + return dialer.DialContext(dialCtx, "tcp", addr) + }), + ) + if err == nil { + client = pb.NewSimpleServiceClient(conn) + } + return +} + +type simpleService struct{} + +func (simpleService) JoinStrings(ctx context.Context, req *pb.JoinStringsRequest) (*pb.JoinStringsResponse, error) { + return &pb.JoinStringsResponse{Joined: strings.Join(req.Strings, req.Delimiter)}, nil +} + +func (simpleService) ProvideStrings(req *pb.ProvideStringsRequest, srv pb.SimpleService_ProvideStringsServer) error { + for i := 0; uint32(i) < req.Count; i++ { + if err := srv.Send(&pb.ProvideStringsResponse{String_: fmt.Sprintf("string-%v", i+1)}); err != nil { + return err + } + } + return nil +} + +func (simpleService) ReceiveStrings(srv pb.SimpleService_ReceiveStringsServer) error { + resp := &pb.ReceiveStringsResponse{} + for { + if req, err := srv.Recv(); err == io.EOF { + return srv.SendAndClose(resp) + } else if err != nil { + return err + } else { + resp.Received = append(resp.Received, req.String_) + } + } +} + +func (simpleService) ExchangeStrings(srv pb.SimpleService_ExchangeStringsServer) error { + resp := &pb.ExchangeStringsResponse{} + for { + if req, err := srv.Recv(); err == io.EOF { + return srv.Send(resp) + } else if err != nil { + return err + } else { + resp.Received = append(resp.Received, req.String_) + if req.WantReturn { + if err := srv.Send(resp); err != nil { + return err + } + resp = &pb.ExchangeStringsResponse{} + } + } + } +} diff --git a/examples/grpc/pb/service.pb.go b/examples/grpc/pb/service.pb.go new file mode 100644 index 0000000..1796fea --- /dev/null +++ b/examples/grpc/pb/service.pb.go @@ -0,0 +1,487 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: service.proto + +/* +Package pb is a generated protocol buffer package. + +It is generated from these files: + service.proto + +It has these top-level messages: + JoinStringsRequest + JoinStringsResponse + ProvideStringsRequest + ProvideStringsResponse + ReceiveStringsRequest + ReceiveStringsResponse + ExchangeStringsRequest + ExchangeStringsResponse +*/ +package pb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type JoinStringsRequest struct { + Strings []string `protobuf:"bytes,1,rep,name=strings" json:"strings,omitempty"` + Delimiter string `protobuf:"bytes,2,opt,name=delimiter" json:"delimiter,omitempty"` +} + +func (m *JoinStringsRequest) Reset() { *m = JoinStringsRequest{} } +func (m *JoinStringsRequest) String() string { return proto.CompactTextString(m) } +func (*JoinStringsRequest) ProtoMessage() {} +func (*JoinStringsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *JoinStringsRequest) GetStrings() []string { + if m != nil { + return m.Strings + } + return nil +} + +func (m *JoinStringsRequest) GetDelimiter() string { + if m != nil { + return m.Delimiter + } + return "" +} + +type JoinStringsResponse struct { + Joined string `protobuf:"bytes,1,opt,name=joined" json:"joined,omitempty"` +} + +func (m *JoinStringsResponse) Reset() { *m = JoinStringsResponse{} } +func (m *JoinStringsResponse) String() string { return proto.CompactTextString(m) } +func (*JoinStringsResponse) ProtoMessage() {} +func (*JoinStringsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *JoinStringsResponse) GetJoined() string { + if m != nil { + return m.Joined + } + return "" +} + +type ProvideStringsRequest struct { + Count uint32 `protobuf:"varint,1,opt,name=count" json:"count,omitempty"` +} + +func (m *ProvideStringsRequest) Reset() { *m = ProvideStringsRequest{} } +func (m *ProvideStringsRequest) String() string { return proto.CompactTextString(m) } +func (*ProvideStringsRequest) ProtoMessage() {} +func (*ProvideStringsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *ProvideStringsRequest) GetCount() uint32 { + if m != nil { + return m.Count + } + return 0 +} + +type ProvideStringsResponse struct { + String_ string `protobuf:"bytes,1,opt,name=string" json:"string,omitempty"` +} + +func (m *ProvideStringsResponse) Reset() { *m = ProvideStringsResponse{} } +func (m *ProvideStringsResponse) String() string { return proto.CompactTextString(m) } +func (*ProvideStringsResponse) ProtoMessage() {} +func (*ProvideStringsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *ProvideStringsResponse) GetString_() string { + if m != nil { + return m.String_ + } + return "" +} + +type ReceiveStringsRequest struct { + String_ string `protobuf:"bytes,1,opt,name=string" json:"string,omitempty"` +} + +func (m *ReceiveStringsRequest) Reset() { *m = ReceiveStringsRequest{} } +func (m *ReceiveStringsRequest) String() string { return proto.CompactTextString(m) } +func (*ReceiveStringsRequest) ProtoMessage() {} +func (*ReceiveStringsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *ReceiveStringsRequest) GetString_() string { + if m != nil { + return m.String_ + } + return "" +} + +type ReceiveStringsResponse struct { + Received []string `protobuf:"bytes,1,rep,name=received" json:"received,omitempty"` +} + +func (m *ReceiveStringsResponse) Reset() { *m = ReceiveStringsResponse{} } +func (m *ReceiveStringsResponse) String() string { return proto.CompactTextString(m) } +func (*ReceiveStringsResponse) ProtoMessage() {} +func (*ReceiveStringsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *ReceiveStringsResponse) GetReceived() []string { + if m != nil { + return m.Received + } + return nil +} + +type ExchangeStringsRequest struct { + String_ string `protobuf:"bytes,1,opt,name=string" json:"string,omitempty"` + WantReturn bool `protobuf:"varint,2,opt,name=want_return,json=wantReturn" json:"want_return,omitempty"` +} + +func (m *ExchangeStringsRequest) Reset() { *m = ExchangeStringsRequest{} } +func (m *ExchangeStringsRequest) String() string { return proto.CompactTextString(m) } +func (*ExchangeStringsRequest) ProtoMessage() {} +func (*ExchangeStringsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *ExchangeStringsRequest) GetString_() string { + if m != nil { + return m.String_ + } + return "" +} + +func (m *ExchangeStringsRequest) GetWantReturn() bool { + if m != nil { + return m.WantReturn + } + return false +} + +type ExchangeStringsResponse struct { + Received []string `protobuf:"bytes,1,rep,name=received" json:"received,omitempty"` +} + +func (m *ExchangeStringsResponse) Reset() { *m = ExchangeStringsResponse{} } +func (m *ExchangeStringsResponse) String() string { return proto.CompactTextString(m) } +func (*ExchangeStringsResponse) ProtoMessage() {} +func (*ExchangeStringsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *ExchangeStringsResponse) GetReceived() []string { + if m != nil { + return m.Received + } + return nil +} + +func init() { + proto.RegisterType((*JoinStringsRequest)(nil), "pb.JoinStringsRequest") + proto.RegisterType((*JoinStringsResponse)(nil), "pb.JoinStringsResponse") + proto.RegisterType((*ProvideStringsRequest)(nil), "pb.ProvideStringsRequest") + proto.RegisterType((*ProvideStringsResponse)(nil), "pb.ProvideStringsResponse") + proto.RegisterType((*ReceiveStringsRequest)(nil), "pb.ReceiveStringsRequest") + proto.RegisterType((*ReceiveStringsResponse)(nil), "pb.ReceiveStringsResponse") + proto.RegisterType((*ExchangeStringsRequest)(nil), "pb.ExchangeStringsRequest") + proto.RegisterType((*ExchangeStringsResponse)(nil), "pb.ExchangeStringsResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for SimpleService service + +type SimpleServiceClient interface { + JoinStrings(ctx context.Context, in *JoinStringsRequest, opts ...grpc.CallOption) (*JoinStringsResponse, error) + ProvideStrings(ctx context.Context, in *ProvideStringsRequest, opts ...grpc.CallOption) (SimpleService_ProvideStringsClient, error) + ReceiveStrings(ctx context.Context, opts ...grpc.CallOption) (SimpleService_ReceiveStringsClient, error) + ExchangeStrings(ctx context.Context, opts ...grpc.CallOption) (SimpleService_ExchangeStringsClient, error) +} + +type simpleServiceClient struct { + cc *grpc.ClientConn +} + +func NewSimpleServiceClient(cc *grpc.ClientConn) SimpleServiceClient { + return &simpleServiceClient{cc} +} + +func (c *simpleServiceClient) JoinStrings(ctx context.Context, in *JoinStringsRequest, opts ...grpc.CallOption) (*JoinStringsResponse, error) { + out := new(JoinStringsResponse) + err := grpc.Invoke(ctx, "/pb.SimpleService/JoinStrings", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *simpleServiceClient) ProvideStrings(ctx context.Context, in *ProvideStringsRequest, opts ...grpc.CallOption) (SimpleService_ProvideStringsClient, error) { + stream, err := grpc.NewClientStream(ctx, &_SimpleService_serviceDesc.Streams[0], c.cc, "/pb.SimpleService/ProvideStrings", opts...) + if err != nil { + return nil, err + } + x := &simpleServiceProvideStringsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type SimpleService_ProvideStringsClient interface { + Recv() (*ProvideStringsResponse, error) + grpc.ClientStream +} + +type simpleServiceProvideStringsClient struct { + grpc.ClientStream +} + +func (x *simpleServiceProvideStringsClient) Recv() (*ProvideStringsResponse, error) { + m := new(ProvideStringsResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *simpleServiceClient) ReceiveStrings(ctx context.Context, opts ...grpc.CallOption) (SimpleService_ReceiveStringsClient, error) { + stream, err := grpc.NewClientStream(ctx, &_SimpleService_serviceDesc.Streams[1], c.cc, "/pb.SimpleService/ReceiveStrings", opts...) + if err != nil { + return nil, err + } + x := &simpleServiceReceiveStringsClient{stream} + return x, nil +} + +type SimpleService_ReceiveStringsClient interface { + Send(*ReceiveStringsRequest) error + CloseAndRecv() (*ReceiveStringsResponse, error) + grpc.ClientStream +} + +type simpleServiceReceiveStringsClient struct { + grpc.ClientStream +} + +func (x *simpleServiceReceiveStringsClient) Send(m *ReceiveStringsRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *simpleServiceReceiveStringsClient) CloseAndRecv() (*ReceiveStringsResponse, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(ReceiveStringsResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *simpleServiceClient) ExchangeStrings(ctx context.Context, opts ...grpc.CallOption) (SimpleService_ExchangeStringsClient, error) { + stream, err := grpc.NewClientStream(ctx, &_SimpleService_serviceDesc.Streams[2], c.cc, "/pb.SimpleService/ExchangeStrings", opts...) + if err != nil { + return nil, err + } + x := &simpleServiceExchangeStringsClient{stream} + return x, nil +} + +type SimpleService_ExchangeStringsClient interface { + Send(*ExchangeStringsRequest) error + Recv() (*ExchangeStringsResponse, error) + grpc.ClientStream +} + +type simpleServiceExchangeStringsClient struct { + grpc.ClientStream +} + +func (x *simpleServiceExchangeStringsClient) Send(m *ExchangeStringsRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *simpleServiceExchangeStringsClient) Recv() (*ExchangeStringsResponse, error) { + m := new(ExchangeStringsResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for SimpleService service + +type SimpleServiceServer interface { + JoinStrings(context.Context, *JoinStringsRequest) (*JoinStringsResponse, error) + ProvideStrings(*ProvideStringsRequest, SimpleService_ProvideStringsServer) error + ReceiveStrings(SimpleService_ReceiveStringsServer) error + ExchangeStrings(SimpleService_ExchangeStringsServer) error +} + +func RegisterSimpleServiceServer(s *grpc.Server, srv SimpleServiceServer) { + s.RegisterService(&_SimpleService_serviceDesc, srv) +} + +func _SimpleService_JoinStrings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(JoinStringsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SimpleServiceServer).JoinStrings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.SimpleService/JoinStrings", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SimpleServiceServer).JoinStrings(ctx, req.(*JoinStringsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SimpleService_ProvideStrings_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ProvideStringsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(SimpleServiceServer).ProvideStrings(m, &simpleServiceProvideStringsServer{stream}) +} + +type SimpleService_ProvideStringsServer interface { + Send(*ProvideStringsResponse) error + grpc.ServerStream +} + +type simpleServiceProvideStringsServer struct { + grpc.ServerStream +} + +func (x *simpleServiceProvideStringsServer) Send(m *ProvideStringsResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _SimpleService_ReceiveStrings_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SimpleServiceServer).ReceiveStrings(&simpleServiceReceiveStringsServer{stream}) +} + +type SimpleService_ReceiveStringsServer interface { + SendAndClose(*ReceiveStringsResponse) error + Recv() (*ReceiveStringsRequest, error) + grpc.ServerStream +} + +type simpleServiceReceiveStringsServer struct { + grpc.ServerStream +} + +func (x *simpleServiceReceiveStringsServer) SendAndClose(m *ReceiveStringsResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *simpleServiceReceiveStringsServer) Recv() (*ReceiveStringsRequest, error) { + m := new(ReceiveStringsRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _SimpleService_ExchangeStrings_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SimpleServiceServer).ExchangeStrings(&simpleServiceExchangeStringsServer{stream}) +} + +type SimpleService_ExchangeStringsServer interface { + Send(*ExchangeStringsResponse) error + Recv() (*ExchangeStringsRequest, error) + grpc.ServerStream +} + +type simpleServiceExchangeStringsServer struct { + grpc.ServerStream +} + +func (x *simpleServiceExchangeStringsServer) Send(m *ExchangeStringsResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *simpleServiceExchangeStringsServer) Recv() (*ExchangeStringsRequest, error) { + m := new(ExchangeStringsRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _SimpleService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pb.SimpleService", + HandlerType: (*SimpleServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "JoinStrings", + Handler: _SimpleService_JoinStrings_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "ProvideStrings", + Handler: _SimpleService_ProvideStrings_Handler, + ServerStreams: true, + }, + { + StreamName: "ReceiveStrings", + Handler: _SimpleService_ReceiveStrings_Handler, + ClientStreams: true, + }, + { + StreamName: "ExchangeStrings", + Handler: _SimpleService_ExchangeStrings_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "service.proto", +} + +func init() { proto.RegisterFile("service.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x4f, 0x4f, 0x3a, 0x31, + 0x14, 0x4c, 0xf9, 0xe5, 0x87, 0xf0, 0x08, 0x9a, 0x54, 0x59, 0xd6, 0xd5, 0x44, 0xd2, 0x13, 0x17, + 0x90, 0xf8, 0xe7, 0xea, 0xcd, 0x83, 0xc6, 0x18, 0x2d, 0x1f, 0xc0, 0xc0, 0xee, 0x0b, 0xd6, 0x40, + 0xbb, 0xb6, 0x05, 0xfd, 0x62, 0x7e, 0x3f, 0x43, 0xbb, 0x88, 0x2c, 0x35, 0x7a, 0x9c, 0x79, 0xef, + 0xcd, 0x34, 0x33, 0x29, 0x34, 0x0d, 0xea, 0x85, 0x48, 0xb1, 0x9f, 0x6b, 0x65, 0x15, 0xad, 0xe4, + 0x63, 0x76, 0x07, 0xf4, 0x56, 0x09, 0x39, 0xb4, 0x5a, 0xc8, 0x89, 0xe1, 0xf8, 0x3a, 0x47, 0x63, + 0x69, 0x0c, 0x3b, 0xc6, 0x33, 0x31, 0xe9, 0xfc, 0xeb, 0xd6, 0xf9, 0x0a, 0xd2, 0x63, 0xa8, 0x67, + 0x38, 0x15, 0x33, 0x61, 0x51, 0xc7, 0x95, 0x0e, 0xe9, 0xd6, 0xf9, 0x9a, 0x60, 0x3d, 0xd8, 0xdf, + 0x50, 0x33, 0xb9, 0x92, 0x06, 0x69, 0x04, 0xd5, 0x17, 0x25, 0x24, 0x66, 0x31, 0x71, 0x17, 0x05, + 0x62, 0x3d, 0x68, 0x3d, 0x68, 0xb5, 0x10, 0x19, 0x96, 0xfc, 0x0f, 0xe0, 0x7f, 0xaa, 0xe6, 0xd2, + 0xba, 0xfd, 0x26, 0xf7, 0x80, 0x0d, 0x20, 0x2a, 0xaf, 0xaf, 0x0d, 0xfc, 0x03, 0x57, 0x06, 0x1e, + 0xb1, 0x53, 0x68, 0x71, 0x4c, 0x51, 0x2c, 0xca, 0x06, 0x3f, 0x1d, 0x5c, 0x40, 0x54, 0x3e, 0x28, + 0x2c, 0x12, 0xa8, 0x69, 0x3f, 0xc9, 0x8a, 0x4c, 0xbe, 0x30, 0x7b, 0x84, 0xe8, 0xfa, 0x3d, 0x7d, + 0x1e, 0xc9, 0xc9, 0x1f, 0x7d, 0xe8, 0x09, 0x34, 0xde, 0x46, 0xd2, 0x3e, 0x69, 0xb4, 0x73, 0x2d, + 0x5d, 0x90, 0x35, 0x0e, 0x4b, 0x8a, 0x3b, 0x86, 0x5d, 0x42, 0x7b, 0x4b, 0xf2, 0xf7, 0x97, 0x9c, + 0x7d, 0x54, 0xa0, 0x39, 0x14, 0xb3, 0x7c, 0x8a, 0x43, 0x5f, 0x35, 0xbd, 0x82, 0xc6, 0xb7, 0x4a, + 0x68, 0xd4, 0xcf, 0xc7, 0xfd, 0xed, 0xc6, 0x93, 0xf6, 0x16, 0x5f, 0xb8, 0xdd, 0xc0, 0xee, 0x66, + 0xe8, 0xf4, 0x70, 0xb9, 0x1a, 0xec, 0x2d, 0x49, 0x42, 0x23, 0x2f, 0x34, 0x20, 0x4b, 0xa9, 0xcd, + 0x70, 0xbd, 0x54, 0xb0, 0x21, 0x2f, 0x15, 0xee, 0xa2, 0x4b, 0xe8, 0x3d, 0xec, 0x95, 0xe2, 0xa1, + 0xee, 0x20, 0x5c, 0x43, 0x72, 0x14, 0x9c, 0xad, 0xd4, 0x06, 0x64, 0x5c, 0x75, 0x3f, 0xe2, 0xfc, + 0x33, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x5e, 0xf9, 0x7a, 0x22, 0x03, 0x00, 0x00, +} diff --git a/examples/grpc/pb/service.proto b/examples/grpc/pb/service.proto new file mode 100644 index 0000000..cdb3339 --- /dev/null +++ b/examples/grpc/pb/service.proto @@ -0,0 +1,48 @@ +/* +To regen, with `protoc` on the `PATH` and `protoc-gen-go` on the `PATH` (usually via `$GOPATH/bin`), from this dir run: + + protoc --go_out=plugins=grpc:. service.proto +*/ +syntax = "proto3"; +package pb; + +service SimpleService { + rpc JoinStrings(JoinStringsRequest) returns (JoinStringsResponse); + rpc ProvideStrings(ProvideStringsRequest) returns (stream ProvideStringsResponse); + rpc ReceiveStrings(stream ReceiveStringsRequest) returns (ReceiveStringsResponse); + rpc ExchangeStrings(stream ExchangeStringsRequest) returns (stream ExchangeStringsResponse); +} + +message JoinStringsRequest { + repeated string strings = 1; + string delimiter = 2; +} + +message JoinStringsResponse { + string joined = 1; +} + +message ProvideStringsRequest { + uint32 count = 1; +} + +message ProvideStringsResponse { + string string = 1; +} + +message ReceiveStringsRequest { + string string = 1; +} + +message ReceiveStringsResponse { + repeated string received = 1; +} + +message ExchangeStringsRequest { + string string = 1; + bool want_return = 2; +} + +message ExchangeStringsResponse { + repeated string received = 1; +} \ No newline at end of file diff --git a/tor/listen.go b/tor/listen.go index c273f2d..6b142d2 100644 --- a/tor/listen.go +++ b/tor/listen.go @@ -73,7 +73,7 @@ type ListenConf struct { // Version3 determines whether, when Key is nil, a version 2 or version 3 // service/key will be generated. If true it is version 3 (an ed25519 key - // and v3 onion service) and if false it is version 2 (a RSA-2014 key and v2 + // and v3 onion service) and if false it is version 2 (a RSA-1024 key and v2 // onion service). If Key is not nil, this value is ignored. Version3 bool @@ -106,9 +106,9 @@ type ListenConf struct { // false, the stream is simply not connected but the circuit stays open. MaxStreamsCloseCircuit bool - // NoWait if true will not wait until the onion service is built. If false, - // the network will be enabled if it's not and then we will wait until - // the onion service is built. + // NoWait if true will not wait until the onion service is published. If + // false, the network will be enabled if it's not and then we will wait + // until the onion service is published. NoWait bool } diff --git a/tor/tor.go b/tor/tor.go index 2dc407a..f736b41 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -92,7 +92,7 @@ type StartConf struct { // started. ExtraArgs []string - // TorrcFile is the torrc file to on start. If empty, a blank torrc is + // TorrcFile is the torrc file to set on start. If empty, a blank torrc is // created in the data directory and is used instead. TorrcFile string