├── .editorconfig ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── changelog.md ├── client.go ├── conn.go ├── doc.go ├── examples ├── message.pb │ ├── arith.pb.go │ ├── arith.proto │ ├── echo.pb.go │ ├── echo.proto │ └── proto.go ├── proto3.pb │ ├── Makefile │ ├── proto.go │ ├── proto3.pb.go │ ├── proto3.pb.protorpc.go │ ├── proto3.proto │ └── proto3_proto_test.go ├── service.pb │ ├── Makefile │ ├── all_test.go │ ├── arith.go │ ├── arith.pb.go │ ├── arith.pb.protorpc.go │ ├── arith.proto │ ├── arith_test.go │ ├── echo.go │ ├── echo.pb.go │ ├── echo.pb.protorpc.go │ ├── echo.proto │ ├── echo_test.go │ └── proto.go └── stdrpc.pb │ ├── Makefile │ ├── arith.pb.go │ ├── arith.proto │ ├── echo.pb.go │ └── echo.proto ├── go.mod ├── go.sum ├── hello.go ├── hello2.go ├── protoc-gen-plugin ├── generator.go ├── main.go └── main_plugin.go ├── protoc-gen-protorpc ├── env.go └── main.go ├── protoc-gen-stdrpc ├── _main-ignore.go ├── main.go └── netrpc.go ├── rpc_test.go ├── server.go ├── wire.go └── wire.pb ├── proto.go ├── wire.pb.go └── wire.proto /.editorconfig: -------------------------------------------------------------------------------- 1 | # Copyright 2018 . All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | # http://editorconfig.org/ 6 | 7 | root = true 8 | 9 | # Unix-style newlines with a newline ending every file 10 | [*] 11 | charset = utf-8 12 | end_of_line = lf 13 | trim_trailing_whitespace = true 14 | insert_final_newline = true 15 | 16 | [*] 17 | indent_style = tab 18 | indent_size = 4 19 | tab_width = 4 20 | 21 | [*.{go,proto}] 22 | charset = utf-8 23 | indent_style = tab 24 | tab_width = 4 25 | 26 | # Matches the exact files either package.json or .travis.yml 27 | [{package.json,.travis.yml}] 28 | indent_style = space 29 | indent_size = 2 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.13 5 | - 1.14 6 | - 1.15 7 | - 1.16 8 | - tip 9 | 10 | before_script: 11 | - go get github.com/golang/snappy 12 | - go get github.com/golang/protobuf/proto 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 . All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | FROM golang:1.9.2-alpine3.6 as builder 6 | 7 | RUN apk add --no-cache git curl openssl 8 | 9 | RUN go get github.com/golang/protobuf/protoc-gen-go 10 | RUN go get github.com/chai2010/protorpc/protoc-gen-protorpc 11 | RUN go get github.com/chai2010/protorpc/protoc-gen-stdrpc 12 | 13 | # the protoc can't run on alpine, 14 | # we only need the protobuf's stdarnd library in the `/protoc/include`. 15 | RUN mkdir -p /protoc && cd /protoc \ 16 | && wget https://github.com/google/protobuf/releases/download/v3.5.0/protoc-3.5.0-linux-x86_64.zip \ 17 | && unzip protoc-3.5.0-linux-x86_64.zip 18 | 19 | FROM golang:1.9.2-alpine3.6 20 | 21 | RUN apk add --no-cache git protobuf make curl openssl 22 | 23 | COPY --from=builder /protoc/include /usr/local/include 24 | COPY --from=builder /go/bin /go/bin -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, chai2010 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | - *Go语言QQ群: 102319854, 1055927514* 2 | - *凹语言(凹读音“Wa”)(The Wa Programming Language): https://github.com/wa-lang/wa* 3 | 4 | ---- 5 | 6 | # protorpc 7 | 8 | ``` 9 | ██████╗ ██████╗ ██████╗ ████████╗ ██████╗ ██████╗ ██████╗ ██████╗ 10 | ██╔══██╗██╔══██╗██╔═══██╗╚══██╔══╝██╔═══██╗ ██╔══██╗██╔══██╗██╔════╝ 11 | ██████╔╝██████╔╝██║ ██║ ██║ ██║ ██║█████╗██████╔╝██████╔╝██║ 12 | ██╔═══╝ ██╔══██╗██║ ██║ ██║ ██║ ██║╚════╝██╔══██╗██╔═══╝ ██║ 13 | ██║ ██║ ██║╚██████╔╝ ██║ ╚██████╔╝ ██║ ██║██║ ╚██████╗ 14 | ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ 15 | ``` 16 | 17 | [![Build Status](https://travis-ci.org/chai2010/protorpc.svg)](https://travis-ci.org/chai2010/protorpc) 18 | [![GoDoc](https://godoc.org/github.com/chai2010/protorpc?status.svg)](https://godoc.org/github.com/chai2010/protorpc) 19 | 20 | - C++ Version(Proto2): [https://github.com/chai2010/protorpc.cxx](https://github.com/chai2010/protorpc.cxx) 21 | - C++ Version(Proto3): [https://github.com/chai2010/protorpc3-cxx](https://github.com/chai2010/protorpc3-cxx) 22 | - Talks: [Go/C++语言Protobuf-RPC简介](http://go-talks.appspot.com/github.com/chai2010/talks/chai2010-protorpc-intro.slide) 23 | 24 | # Install 25 | 26 | Install `protorpc` package: 27 | 28 | 1. `go install github.com/golang/protobuf/protoc-gen-go` 29 | 1. `go get github.com/chai2010/protorpc` 30 | 1. `go run hello.go` 31 | 32 | Install `protoc-gen-go` plugin: 33 | 34 | 1. install `protoc` at first: http://github.com/google/protobuf/releases 35 | 1. `go get github.com/golang/protobuf/protoc-gen-go` 36 | 1. `go get github.com/chai2010/protorpc/protoc-gen-protorpc` 37 | 1. `go generate github.com/chai2010/protorpc/examples/service.pb` 38 | 1. `go test github.com/chai2010/protorpc/examples/service.pb` 39 | 40 | 41 | # Examples 42 | 43 | First, create [echo.proto](examples/service.pb/echo.proto): 44 | 45 | ```Proto 46 | syntax = "proto3"; 47 | 48 | package service; 49 | 50 | message EchoRequest { 51 | string msg = 1; 52 | } 53 | 54 | message EchoResponse { 55 | string msg = 1; 56 | } 57 | 58 | service EchoService { 59 | rpc Echo (EchoRequest) returns (EchoResponse); 60 | rpc EchoTwice (EchoRequest) returns (EchoResponse); 61 | } 62 | ``` 63 | 64 | Second, generate [echo.pb.go](examples/service.pb/echo.pb.go) and [echo.pb.protorpc.go](examples/service.pb/echo.pb.protorpc.go) 65 | from [echo.proto](examples/service.pb/echo.proto) (we can use `go generate` to invoke this command, see [proto.go](examples/service.pb/proto.go)). 66 | 67 | protoc --go_out=. echo.proto 68 | protoc --protorpc_out=. echo.proto 69 | 70 | 71 | Now, we can use the stub code like this: 72 | 73 | ```Go 74 | package main 75 | 76 | import ( 77 | "fmt" 78 | "log" 79 | 80 | "github.com/chai2010/protorpc" 81 | service "github.com/chai2010/protorpc/examples/service.pb" 82 | ) 83 | 84 | type Echo int 85 | 86 | func (t *Echo) Echo(args *service.EchoRequest, reply *service.EchoResponse) error { 87 | reply.Msg = args.Msg 88 | return nil 89 | } 90 | 91 | func (t *Echo) EchoTwice(args *service.EchoRequest, reply *service.EchoResponse) error { 92 | reply.Msg = args.Msg + args.Msg 93 | return nil 94 | } 95 | 96 | func init() { 97 | go service.ListenAndServeEchoService("tcp", `127.0.0.1:9527`, new(Echo)) 98 | } 99 | 100 | func main() { 101 | echoClient, err := service.DialEchoService("tcp", `127.0.0.1:9527`) 102 | if err != nil { 103 | log.Fatalf("service.DialEchoService: %v", err) 104 | } 105 | defer echoClient.Close() 106 | 107 | args := &service.EchoRequest{Msg: "你好, 世界!"} 108 | reply, err := echoClient.EchoTwice(args) 109 | if err != nil { 110 | log.Fatalf("echoClient.EchoTwice: %v", err) 111 | } 112 | fmt.Println(reply.Msg) 113 | 114 | // or use normal client 115 | client, err := protorpc.Dial("tcp", `127.0.0.1:9527`) 116 | if err != nil { 117 | log.Fatalf("protorpc.Dial: %v", err) 118 | } 119 | defer client.Close() 120 | 121 | echoClient1 := &service.EchoServiceClient{client} 122 | echoClient2 := &service.EchoServiceClient{client} 123 | reply, err = echoClient1.EchoTwice(args) 124 | reply, err = echoClient2.EchoTwice(args) 125 | _, _ = reply, err 126 | 127 | // Output: 128 | // 你好, 世界!你好, 世界! 129 | } 130 | ``` 131 | 132 | [More examples](examples). 133 | 134 | # standard net/rpc 135 | 136 | First, create [echo.proto](examples/stdrpc.pb/echo.proto): 137 | 138 | ```Proto 139 | syntax = "proto3"; 140 | 141 | package service; 142 | 143 | message EchoRequest { 144 | string msg = 1; 145 | } 146 | 147 | message EchoResponse { 148 | string msg = 1; 149 | } 150 | 151 | service EchoService { 152 | rpc Echo (EchoRequest) returns (EchoResponse); 153 | rpc EchoTwice (EchoRequest) returns (EchoResponse); 154 | } 155 | ``` 156 | 157 | Second, generate [echo.pb.go](examples/stdrpc.pb/echo.pb.go) from [echo.proto](examples/stdrpc.pb/echo.proto) with `protoc-gen-stdrpc` plugin. 158 | 159 | protoc --stdrpc_out=. echo.proto 160 | 161 | The stdrpc plugin generated code do not depends **protorpc** package, it use gob as the default rpc encoding. 162 | 163 | # Add prefix 164 | 165 | ``` 166 | $ ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX=abc protoc --protorpc_out=. x.proto 167 | ``` 168 | 169 | # BUGS 170 | 171 | Report bugs to . 172 | 173 | Thanks! 174 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelogs 2 | 3 | ## 1.1.3 - 2021.7.12 4 | 5 | - fix `readRequestHeader` maxSize, response error maybe very long 6 | 7 | ## 1.1.2 - 2021.7.6 8 | 9 | - fix `UseSnappy` typo 10 | 11 | ## 1.1.1 - 2021.7.4 12 | 13 | - protoc-gen-plugin: ignore format error 14 | 15 | ## 1.1.0 - 2021.7.4 16 | 17 | - add `UseSappy` and `UseCrc32ChecksumIEEE` 18 | - add `ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX` env flag 19 | - fix frame size overflow panic (issue12) 20 | 21 | ## 1.0.0 - go mod version (2018) 22 | 23 | - init version 24 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package protorpc 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | "net" 11 | "net/rpc" 12 | "sync" 13 | "time" 14 | 15 | wire "github.com/chai2010/protorpc/wire.pb" 16 | "github.com/golang/protobuf/proto" 17 | ) 18 | 19 | type clientCodec struct { 20 | r io.Reader 21 | w io.Writer 22 | c io.Closer 23 | 24 | // temporary work space 25 | respHeader wire.ResponseHeader 26 | 27 | // Protobuf-RPC responses include the request id but not the request method. 28 | // Package rpc expects both. 29 | // We save the request method in pending when sending a request 30 | // and then look it up by request ID when filling out the rpc Response. 31 | mutex sync.Mutex // protects pending 32 | pending map[uint64]string // map request id to method name 33 | } 34 | 35 | // NewClientCodec returns a new rpc.ClientCodec using Protobuf-RPC on conn. 36 | func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec { 37 | return &clientCodec{ 38 | r: conn, 39 | w: conn, 40 | c: conn, 41 | pending: make(map[uint64]string), 42 | } 43 | } 44 | 45 | func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) error { 46 | c.mutex.Lock() 47 | c.pending[r.Seq] = r.ServiceMethod 48 | c.mutex.Unlock() 49 | 50 | var request proto.Message 51 | if param != nil { 52 | var ok bool 53 | if request, ok = param.(proto.Message); !ok { 54 | return fmt.Errorf( 55 | "protorpc.ClientCodec.WriteRequest: %T does not implement proto.Message", 56 | param, 57 | ) 58 | } 59 | } 60 | err := writeRequest(c.w, r.Seq, r.ServiceMethod, request) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | return nil 66 | } 67 | 68 | func (c *clientCodec) ReadResponseHeader(r *rpc.Response) error { 69 | header := wire.ResponseHeader{} 70 | err := readResponseHeader(c.r, &header) 71 | if err != nil { 72 | return err 73 | } 74 | 75 | c.mutex.Lock() 76 | r.Seq = header.Id 77 | r.Error = header.Error 78 | r.ServiceMethod = c.pending[r.Seq] 79 | delete(c.pending, r.Seq) 80 | c.mutex.Unlock() 81 | 82 | c.respHeader = header 83 | return nil 84 | } 85 | 86 | func (c *clientCodec) ReadResponseBody(x interface{}) error { 87 | var response proto.Message 88 | if x != nil { 89 | var ok bool 90 | response, ok = x.(proto.Message) 91 | if !ok { 92 | return fmt.Errorf( 93 | "protorpc.ClientCodec.ReadResponseBody: %T does not implement proto.Message", 94 | x, 95 | ) 96 | } 97 | } 98 | 99 | err := readResponseBody(c.r, &c.respHeader, response) 100 | if err != nil { 101 | return nil 102 | } 103 | 104 | c.respHeader = wire.ResponseHeader{} 105 | return nil 106 | } 107 | 108 | // Close closes the underlying connection. 109 | func (c *clientCodec) Close() error { 110 | return c.c.Close() 111 | } 112 | 113 | // NewClient returns a new rpc.Client to handle requests to the 114 | // set of services at the other end of the connection. 115 | func NewClient(conn io.ReadWriteCloser) *rpc.Client { 116 | return rpc.NewClientWithCodec(NewClientCodec(conn)) 117 | } 118 | 119 | // Dial connects to a Protobuf-RPC server at the specified network address. 120 | func Dial(network, address string) (*rpc.Client, error) { 121 | conn, err := net.Dial(network, address) 122 | if err != nil { 123 | return nil, err 124 | } 125 | return NewClient(conn), err 126 | } 127 | 128 | // DialTimeout connects to a Protobuf-RPC server at the specified network address. 129 | func DialTimeout(network, address string, timeout time.Duration) (*rpc.Client, error) { 130 | conn, err := net.DialTimeout(network, address, timeout) 131 | if err != nil { 132 | return nil, err 133 | } 134 | return NewClient(conn), err 135 | } 136 | -------------------------------------------------------------------------------- /conn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package protorpc 6 | 7 | import ( 8 | "encoding/binary" 9 | "errors" 10 | "fmt" 11 | "io" 12 | "net" 13 | ) 14 | 15 | func sendFrame(w io.Writer, data []byte) (err error) { 16 | // Allocate enough space for the biggest uvarint 17 | var size [binary.MaxVarintLen64]byte 18 | 19 | if data == nil || len(data) == 0 { 20 | n := binary.PutUvarint(size[:], uint64(0)) 21 | if err = write(w, size[:n], false); err != nil { 22 | return 23 | } 24 | return 25 | } 26 | 27 | // Write the size and data 28 | n := binary.PutUvarint(size[:], uint64(len(data))) 29 | if err = write(w, size[:n], false); err != nil { 30 | return 31 | } 32 | if err = write(w, data, false); err != nil { 33 | return 34 | } 35 | return 36 | } 37 | 38 | func recvFrame(r io.Reader, maxSize int) (data []byte, err error) { 39 | size, err := readUvarint(r) 40 | if err != nil { 41 | return nil, err 42 | } 43 | if maxSize > 0 { 44 | if int(size) > maxSize { 45 | return nil, fmt.Errorf("protorpc: varint overflows maxSize(%d)", maxSize) 46 | } 47 | } 48 | if size != 0 { 49 | data = make([]byte, size) 50 | if err = read(r, data); err != nil { 51 | return nil, err 52 | } 53 | } 54 | return data, nil 55 | } 56 | 57 | // ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64. 58 | func readUvarint(r io.Reader) (uint64, error) { 59 | var x uint64 60 | var s uint 61 | for i := 0; ; i++ { 62 | var b byte 63 | b, err := readByte(r) 64 | if err != nil { 65 | return 0, err 66 | } 67 | if b < 0x80 { 68 | if i > 9 || i == 9 && b > 1 { 69 | return x, errors.New("protorpc: varint overflows a 64-bit integer") 70 | } 71 | return x | uint64(b)<. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package protorpc implements a Protobuf-RPC ClientCodec and ServerCodec 7 | for the rpc package. 8 | 9 | To install it, you must first have Go (version 1) installed 10 | (see http://golang.org/doc/install). Next, install the standard 11 | protocol buffer implementation from http://github.com/google/protobuf/; 12 | you must be running version 2.3 or higher. 13 | 14 | Finally run 15 | 16 | go get github.com/chai2010/protorpc 17 | go get github.com/chai2010/protorpc/protoc-gen-protorpc 18 | 19 | to install the support library and protocol compiler. 20 | 21 | Here is a simple proto file("arith.pb/arith.proto"): 22 | 23 | package arith; 24 | 25 | message ArithRequest { 26 | optional int32 a = 1; 27 | optional int32 b = 2; 28 | } 29 | 30 | message ArithResponse { 31 | optional int32 val = 1; 32 | optional int32 quo = 2; 33 | optional int32 rem = 3; 34 | } 35 | 36 | service ArithService { 37 | rpc multiply (ArithRequest) returns (ArithResponse); 38 | rpc divide (ArithRequest) returns (ArithResponse); 39 | } 40 | 41 | Then use "protoc-gen-go" to generate "arith.pb.go" file: 42 | 43 | cd arith.pb && protoc --go_out=. arith.proto 44 | 45 | 46 | Use "protoc-gen-protorpc" to generate "arith.pb.protorpc.go" file (include stub code): 47 | 48 | cd arith.pb && protoc --protorpc_out=. arith.proto 49 | 50 | The server calls (for TCP service): 51 | 52 | package server 53 | 54 | import ( 55 | "errors" 56 | 57 | "github.com/golang/protobuf/proto" 58 | 59 | "./arith.pb" 60 | ) 61 | 62 | type Arith int 63 | 64 | func (t *Arith) Multiply(args *arith.ArithRequest, reply *arith.ArithResponse) error { 65 | reply.Val = proto.Int32(args.GetA() * args.GetB()) 66 | return nil 67 | } 68 | 69 | func (t *Arith) Divide(args *arith.ArithRequest, reply *arith.ArithResponse) error { 70 | if args.GetB() == 0 { 71 | return errors.New("divide by zero") 72 | } 73 | reply.Quo = proto.Int32(args.GetA() / args.GetB()) 74 | reply.Rem = proto.Int32(args.GetA() % args.GetB()) 75 | return nil 76 | } 77 | 78 | func main() { 79 | arith.ListenAndServeArithService("tcp", ":1984", new(Arith)) 80 | } 81 | 82 | At this point, clients can see a service "Arith" with methods "ArithService.Multiply" and 83 | "ArithService.Divide". To invoke one, a client first dials the server: 84 | 85 | stub, err := arith.DialArithService("tcp", "127.0.0.1:1984") 86 | if err != nil { 87 | log.Fatal(`arith.DialArithService("tcp", "127.0.0.1:1984"):`, err) 88 | } 89 | defer stub.Close() 90 | 91 | Then it can make a remote call with stub: 92 | 93 | var args ArithRequest 94 | 95 | args.A = proto.Int32(7) 96 | args.B = proto.Int32(8) 97 | reply, err := stub.Multiply(&args, &reply) 98 | if err != nil { 99 | log.Fatal("arith error:", err) 100 | } 101 | fmt.Printf("Arith: %d*%d=%d", args.GetA(), args.GetB(), reply.GetVal()) 102 | 103 | More example: 104 | 105 | go test github.com/chai2010/protorpc/internal/service.pb 106 | 107 | Report bugs to . 108 | 109 | Thanks! 110 | */ 111 | package protorpc // import "github.com/chai2010/protorpc" 112 | -------------------------------------------------------------------------------- /examples/message.pb/arith.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: arith.proto 3 | 4 | /* 5 | Package message is a generated protocol buffer package. 6 | 7 | It is generated from these files: 8 | arith.proto 9 | echo.proto 10 | 11 | It has these top-level messages: 12 | ArithRequest 13 | ArithResponse 14 | EchoRequest 15 | EchoResponse 16 | */ 17 | package message 18 | 19 | import proto "github.com/golang/protobuf/proto" 20 | import fmt "fmt" 21 | import math "math" 22 | 23 | // Reference imports to suppress errors if they are not otherwise used. 24 | var _ = proto.Marshal 25 | var _ = fmt.Errorf 26 | var _ = math.Inf 27 | 28 | // This is a compile-time assertion to ensure that this generated file 29 | // is compatible with the proto package it is being compiled against. 30 | // A compilation error at this line likely means your copy of the 31 | // proto package needs to be updated. 32 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 33 | 34 | type ArithRequest struct { 35 | A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"` 36 | B int32 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"` 37 | } 38 | 39 | func (m *ArithRequest) Reset() { *m = ArithRequest{} } 40 | func (m *ArithRequest) String() string { return proto.CompactTextString(m) } 41 | func (*ArithRequest) ProtoMessage() {} 42 | func (*ArithRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 43 | 44 | func (m *ArithRequest) GetA() int32 { 45 | if m != nil { 46 | return m.A 47 | } 48 | return 0 49 | } 50 | 51 | func (m *ArithRequest) GetB() int32 { 52 | if m != nil { 53 | return m.B 54 | } 55 | return 0 56 | } 57 | 58 | type ArithResponse struct { 59 | C int32 `protobuf:"varint,1,opt,name=c" json:"c,omitempty"` 60 | } 61 | 62 | func (m *ArithResponse) Reset() { *m = ArithResponse{} } 63 | func (m *ArithResponse) String() string { return proto.CompactTextString(m) } 64 | func (*ArithResponse) ProtoMessage() {} 65 | func (*ArithResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } 66 | 67 | func (m *ArithResponse) GetC() int32 { 68 | if m != nil { 69 | return m.C 70 | } 71 | return 0 72 | } 73 | 74 | func init() { 75 | proto.RegisterType((*ArithRequest)(nil), "message.ArithRequest") 76 | proto.RegisterType((*ArithResponse)(nil), "message.ArithResponse") 77 | } 78 | 79 | func init() { proto.RegisterFile("arith.proto", fileDescriptor0) } 80 | 81 | var fileDescriptor0 = []byte{ 82 | // 104 bytes of a gzipped FileDescriptorProto 83 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0x2c, 0xca, 0x2c, 84 | 0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xcf, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 85 | 0x55, 0xd2, 0xe2, 0xe2, 0x71, 0x04, 0x89, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0xf1, 86 | 0x70, 0x31, 0x26, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x31, 0x26, 0x82, 0x78, 0x49, 0x12, 87 | 0x4c, 0x10, 0x5e, 0x92, 0x92, 0x2c, 0x17, 0x2f, 0x54, 0x6d, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0x2a, 88 | 0x48, 0x3a, 0x19, 0xa6, 0x38, 0x39, 0x89, 0x0d, 0x6c, 0xb4, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 89 | 0x61, 0x27, 0x57, 0x32, 0x69, 0x00, 0x00, 0x00, 90 | } 91 | -------------------------------------------------------------------------------- /examples/message.pb/arith.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package message; 8 | 9 | message ArithRequest { 10 | int32 a = 1; 11 | int32 b = 2; 12 | } 13 | 14 | message ArithResponse { 15 | int32 c = 1; 16 | } 17 | -------------------------------------------------------------------------------- /examples/message.pb/echo.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: echo.proto 3 | 4 | package message 5 | 6 | import proto "github.com/golang/protobuf/proto" 7 | import fmt "fmt" 8 | import math "math" 9 | 10 | // Reference imports to suppress errors if they are not otherwise used. 11 | var _ = proto.Marshal 12 | var _ = fmt.Errorf 13 | var _ = math.Inf 14 | 15 | type EchoRequest struct { 16 | Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"` 17 | } 18 | 19 | func (m *EchoRequest) Reset() { *m = EchoRequest{} } 20 | func (m *EchoRequest) String() string { return proto.CompactTextString(m) } 21 | func (*EchoRequest) ProtoMessage() {} 22 | func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } 23 | 24 | func (m *EchoRequest) GetMsg() string { 25 | if m != nil { 26 | return m.Msg 27 | } 28 | return "" 29 | } 30 | 31 | type EchoResponse struct { 32 | Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"` 33 | } 34 | 35 | func (m *EchoResponse) Reset() { *m = EchoResponse{} } 36 | func (m *EchoResponse) String() string { return proto.CompactTextString(m) } 37 | func (*EchoResponse) ProtoMessage() {} 38 | func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } 39 | 40 | func (m *EchoResponse) GetMsg() string { 41 | if m != nil { 42 | return m.Msg 43 | } 44 | return "" 45 | } 46 | 47 | func init() { 48 | proto.RegisterType((*EchoRequest)(nil), "message.EchoRequest") 49 | proto.RegisterType((*EchoResponse)(nil), "message.EchoResponse") 50 | } 51 | 52 | func init() { proto.RegisterFile("echo.proto", fileDescriptor1) } 53 | 54 | var fileDescriptor1 = []byte{ 55 | // 95 bytes of a gzipped FileDescriptorProto 56 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8, 57 | 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xcf, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0x55, 58 | 0x92, 0xe7, 0xe2, 0x76, 0x4d, 0xce, 0xc8, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12, 59 | 0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x95, 0x14, 60 | 0xb8, 0x78, 0x20, 0x0a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x31, 0x55, 0x24, 0xb1, 0x81, 0x8d, 61 | 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xcb, 0xea, 0xe4, 0xa6, 0x60, 0x00, 0x00, 0x00, 62 | } 63 | -------------------------------------------------------------------------------- /examples/message.pb/echo.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package message; 8 | 9 | message EchoRequest { 10 | string msg = 1; 11 | } 12 | 13 | message EchoResponse { 14 | string msg = 1; 15 | } 16 | -------------------------------------------------------------------------------- /examples/message.pb/proto.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate protoc --go_out=. arith.proto echo.proto 6 | 7 | package message 8 | -------------------------------------------------------------------------------- /examples/proto3.pb/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2013 . All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PROTO_FILES=$(sort $(wildcard ./*.proto)) 6 | 7 | default: $(PROTO_FILES) Makefile 8 | go install github.com/golang/protobuf/protoc-gen-go 9 | go install github.com/chai2010/protorpc/protoc-gen-protorpc 10 | protoc --go_out=. ${PROTO_FILES} 11 | protoc --protorpc_out=. ${PROTO_FILES} 12 | go test 13 | 14 | clean: 15 | -------------------------------------------------------------------------------- /examples/proto3.pb/proto.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate protoc --go_out=. proto3.proto 6 | //go:generate protoc --protorpc_out=. proto3.proto 7 | 8 | package proto3_proto 9 | -------------------------------------------------------------------------------- /examples/proto3.pb/proto3.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: proto3.proto 3 | 4 | /* 5 | Package proto3_proto is a generated protocol buffer package. 6 | 7 | It is generated from these files: 8 | proto3.proto 9 | 10 | It has these top-level messages: 11 | Message 12 | Nested 13 | MessageWithMap 14 | */ 15 | package proto3_proto 16 | 17 | import proto "github.com/golang/protobuf/proto" 18 | import fmt "fmt" 19 | import math "math" 20 | 21 | // Reference imports to suppress errors if they are not otherwise used. 22 | var _ = proto.Marshal 23 | var _ = fmt.Errorf 24 | var _ = math.Inf 25 | 26 | // This is a compile-time assertion to ensure that this generated file 27 | // is compatible with the proto package it is being compiled against. 28 | // A compilation error at this line likely means your copy of the 29 | // proto package needs to be updated. 30 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 31 | 32 | type Message_Humour int32 33 | 34 | const ( 35 | Message_UNKNOWN Message_Humour = 0 36 | Message_PUNS Message_Humour = 1 37 | Message_SLAPSTICK Message_Humour = 2 38 | Message_BILL_BAILEY Message_Humour = 3 39 | ) 40 | 41 | var Message_Humour_name = map[int32]string{ 42 | 0: "UNKNOWN", 43 | 1: "PUNS", 44 | 2: "SLAPSTICK", 45 | 3: "BILL_BAILEY", 46 | } 47 | var Message_Humour_value = map[string]int32{ 48 | "UNKNOWN": 0, 49 | "PUNS": 1, 50 | "SLAPSTICK": 2, 51 | "BILL_BAILEY": 3, 52 | } 53 | 54 | func (x Message_Humour) String() string { 55 | return proto.EnumName(Message_Humour_name, int32(x)) 56 | } 57 | func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } 58 | 59 | type Message struct { 60 | Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` 61 | Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` 62 | HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm" json:"height_in_cm,omitempty"` 63 | Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` 64 | ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount" json:"result_count,omitempty"` 65 | TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman" json:"true_scotsman,omitempty"` 66 | Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"` 67 | Key []uint64 `protobuf:"varint,5,rep,packed,name=key" json:"key,omitempty"` 68 | Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"` 69 | Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` 70 | } 71 | 72 | func (m *Message) Reset() { *m = Message{} } 73 | func (m *Message) String() string { return proto.CompactTextString(m) } 74 | func (*Message) ProtoMessage() {} 75 | func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 76 | 77 | func (m *Message) GetName() string { 78 | if m != nil { 79 | return m.Name 80 | } 81 | return "" 82 | } 83 | 84 | func (m *Message) GetHilarity() Message_Humour { 85 | if m != nil { 86 | return m.Hilarity 87 | } 88 | return Message_UNKNOWN 89 | } 90 | 91 | func (m *Message) GetHeightInCm() uint32 { 92 | if m != nil { 93 | return m.HeightInCm 94 | } 95 | return 0 96 | } 97 | 98 | func (m *Message) GetData() []byte { 99 | if m != nil { 100 | return m.Data 101 | } 102 | return nil 103 | } 104 | 105 | func (m *Message) GetResultCount() int64 { 106 | if m != nil { 107 | return m.ResultCount 108 | } 109 | return 0 110 | } 111 | 112 | func (m *Message) GetTrueScotsman() bool { 113 | if m != nil { 114 | return m.TrueScotsman 115 | } 116 | return false 117 | } 118 | 119 | func (m *Message) GetScore() float32 { 120 | if m != nil { 121 | return m.Score 122 | } 123 | return 0 124 | } 125 | 126 | func (m *Message) GetKey() []uint64 { 127 | if m != nil { 128 | return m.Key 129 | } 130 | return nil 131 | } 132 | 133 | func (m *Message) GetNested() *Nested { 134 | if m != nil { 135 | return m.Nested 136 | } 137 | return nil 138 | } 139 | 140 | func (m *Message) GetTerrain() map[string]*Nested { 141 | if m != nil { 142 | return m.Terrain 143 | } 144 | return nil 145 | } 146 | 147 | type Nested struct { 148 | Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"` 149 | } 150 | 151 | func (m *Nested) Reset() { *m = Nested{} } 152 | func (m *Nested) String() string { return proto.CompactTextString(m) } 153 | func (*Nested) ProtoMessage() {} 154 | func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } 155 | 156 | func (m *Nested) GetBunny() string { 157 | if m != nil { 158 | return m.Bunny 159 | } 160 | return "" 161 | } 162 | 163 | type MessageWithMap struct { 164 | ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` 165 | } 166 | 167 | func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } 168 | func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } 169 | func (*MessageWithMap) ProtoMessage() {} 170 | func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } 171 | 172 | func (m *MessageWithMap) GetByteMapping() map[bool][]byte { 173 | if m != nil { 174 | return m.ByteMapping 175 | } 176 | return nil 177 | } 178 | 179 | func init() { 180 | proto.RegisterType((*Message)(nil), "proto3_proto.Message") 181 | proto.RegisterType((*Nested)(nil), "proto3_proto.Nested") 182 | proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap") 183 | proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) 184 | } 185 | 186 | func init() { proto.RegisterFile("proto3.proto", fileDescriptor0) } 187 | 188 | var fileDescriptor0 = []byte{ 189 | // 473 bytes of a gzipped FileDescriptorProto 190 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x5f, 0x8b, 0xd3, 0x40, 191 | 0x14, 0xc5, 0x9d, 0xa6, 0xdb, 0x3f, 0x37, 0xe9, 0x1a, 0x86, 0x0a, 0x43, 0x11, 0x19, 0xeb, 0xcb, 192 | 0x20, 0xda, 0x87, 0xea, 0xc3, 0x22, 0xa2, 0x6c, 0x4b, 0xc1, 0xb2, 0x6d, 0x2d, 0xd3, 0x5d, 0x16, 193 | 0x9f, 0xc2, 0x34, 0x3b, 0xb4, 0xc1, 0x66, 0x52, 0x26, 0x93, 0x85, 0x7c, 0x1d, 0x3f, 0xa7, 0x0f, 194 | 0x92, 0x4c, 0xaa, 0x51, 0xea, 0xd3, 0xdc, 0x7b, 0xe6, 0xdc, 0x99, 0x73, 0x7f, 0xe0, 0x1d, 0x75, 195 | 0x62, 0x92, 0x77, 0xa3, 0xf2, 0xc0, 0x55, 0x17, 0x94, 0xc7, 0xf0, 0xa7, 0x03, 0xed, 0xa5, 0x4c, 196 | 0x53, 0xb1, 0x93, 0x18, 0x43, 0x53, 0x89, 0x58, 0x12, 0x44, 0x11, 0xeb, 0xf2, 0xb2, 0xc6, 0x57, 197 | 0xd0, 0xd9, 0x47, 0x07, 0xa1, 0x23, 0x93, 0x93, 0x06, 0x45, 0xec, 0x72, 0xfc, 0x7c, 0x54, 0x7f, 198 | 0x60, 0x54, 0x0d, 0x8f, 0xbe, 0x64, 0x71, 0x92, 0x69, 0xfe, 0xdb, 0x8d, 0x29, 0x78, 0x7b, 0x19, 199 | 0xed, 0xf6, 0x26, 0x88, 0x54, 0x10, 0xc6, 0xc4, 0xa1, 0x88, 0xf5, 0x38, 0x58, 0x6d, 0xae, 0xa6, 200 | 0x71, 0xf1, 0xdf, 0x83, 0x30, 0x82, 0x34, 0x29, 0x62, 0x1e, 0x2f, 0x6b, 0xfc, 0x12, 0x3c, 0x2d, 201 | 0xd3, 0xec, 0x60, 0x82, 0x30, 0xc9, 0x94, 0x21, 0x6d, 0x8a, 0x98, 0xc3, 0x5d, 0xab, 0x4d, 0x0b, 202 | 0x09, 0xbf, 0x82, 0x9e, 0xd1, 0x99, 0x0c, 0xd2, 0x30, 0x31, 0x69, 0x2c, 0x14, 0xe9, 0x50, 0xc4, 203 | 0x3a, 0xdc, 0x2b, 0xc4, 0x4d, 0xa5, 0xe1, 0x3e, 0x5c, 0xa4, 0x61, 0xa2, 0x25, 0xe9, 0x52, 0xc4, 204 | 0x1a, 0xdc, 0x36, 0xd8, 0x07, 0xe7, 0xbb, 0xcc, 0xc9, 0x05, 0x75, 0x58, 0x93, 0x17, 0x25, 0x7e, 205 | 0x03, 0x2d, 0x25, 0x53, 0x23, 0x1f, 0x48, 0x8b, 0x22, 0xe6, 0x8e, 0xfb, 0x7f, 0x6f, 0xb7, 0x2a, 206 | 0xef, 0x78, 0xe5, 0xc1, 0x1f, 0xa1, 0x6d, 0xa4, 0xd6, 0x22, 0x52, 0x04, 0xa8, 0xc3, 0xdc, 0xf1, 207 | 0xf0, 0x3c, 0x8c, 0x5b, 0x6b, 0x9a, 0x29, 0xa3, 0x73, 0x7e, 0x1a, 0x19, 0xac, 0xc1, 0xab, 0x5f, 208 | 0x9c, 0xd2, 0x58, 0xdc, 0x65, 0x9a, 0xd7, 0x70, 0xf1, 0x28, 0x0e, 0x99, 0x2c, 0x51, 0xff, 0x2f, 209 | 0x8c, 0xb5, 0x7c, 0x68, 0x5c, 0xa1, 0xe1, 0x67, 0x68, 0x59, 0xee, 0xd8, 0x85, 0xf6, 0xdd, 0xea, 210 | 0x66, 0xf5, 0xf5, 0x7e, 0xe5, 0x3f, 0xc1, 0x1d, 0x68, 0xae, 0xef, 0x56, 0x1b, 0x1f, 0xe1, 0x1e, 211 | 0x74, 0x37, 0x8b, 0xeb, 0xf5, 0xe6, 0x76, 0x3e, 0xbd, 0xf1, 0x1b, 0xf8, 0x29, 0xb8, 0x93, 0xf9, 212 | 0x62, 0x11, 0x4c, 0xae, 0xe7, 0x8b, 0xd9, 0x37, 0xdf, 0x19, 0xbe, 0x80, 0x96, 0x7d, 0xb5, 0x00, 213 | 0xb6, 0xcd, 0x94, 0x3a, 0xc5, 0xb1, 0xcd, 0xf0, 0x07, 0x82, 0xcb, 0x6a, 0xa9, 0xfb, 0xc8, 0xec, 214 | 0x97, 0xe2, 0x88, 0xd7, 0xe0, 0x6d, 0x73, 0x23, 0x83, 0x58, 0x1c, 0x8f, 0x91, 0xda, 0x11, 0x54, 215 | 0x82, 0x78, 0x7b, 0x16, 0x44, 0x35, 0x33, 0x9a, 0xe4, 0x46, 0x2e, 0xad, 0xdf, 0x32, 0x71, 0xb7, 216 | 0x7f, 0x94, 0xc1, 0x27, 0xf0, 0xff, 0x35, 0xd4, 0xd9, 0x74, 0x2c, 0x9b, 0x7e, 0x9d, 0x8d, 0x57, 217 | 0xa3, 0x30, 0x9e, 0x82, 0x3b, 0x0b, 0xf7, 0xc9, 0x46, 0xea, 0xc7, 0x28, 0x94, 0xf8, 0x3d, 0x34, 218 | 0x8b, 0x16, 0x3f, 0x3b, 0x1b, 0x69, 0x70, 0x5e, 0xde, 0xb6, 0xac, 0xfa, 0x2b, 0x00, 0x00, 0xff, 219 | 0xff, 0xff, 0xc1, 0x87, 0xd6, 0x2d, 0x03, 0x00, 0x00, 220 | } 221 | -------------------------------------------------------------------------------- /examples/proto3.pb/proto3.pb.protorpc.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-protorpc. DO NOT EDIT. 2 | // 3 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc 4 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-plugin-common 5 | // 6 | // source: proto3.proto 7 | 8 | package proto3_proto 9 | 10 | import ( 11 | "fmt" 12 | "io" 13 | "log" 14 | "net" 15 | "net/rpc" 16 | "time" 17 | 18 | "github.com/chai2010/protorpc" 19 | "github.com/golang/protobuf/proto" 20 | ) 21 | 22 | var ( 23 | _ = fmt.Sprint 24 | _ = io.Reader(nil) 25 | _ = log.Print 26 | _ = net.Addr(nil) 27 | _ = rpc.Call{} 28 | _ = time.Second 29 | 30 | _ = proto.String 31 | _ = protorpc.Dial 32 | ) 33 | 34 | type EchoService interface { 35 | Echo(in *Message, out *Message) error 36 | } 37 | 38 | // AcceptEchoServiceClient accepts connections on the listener and serves requests 39 | // for each incoming connection. Accept blocks; the caller typically 40 | // invokes it in a go statement. 41 | func AcceptEchoServiceClient(lis net.Listener, x EchoService) { 42 | srv := rpc.NewServer() 43 | if err := srv.RegisterName("EchoService", x); err != nil { 44 | log.Fatal(err) 45 | } 46 | 47 | for { 48 | conn, err := lis.Accept() 49 | if err != nil { 50 | log.Fatalf("lis.Accept(): %v\n", err) 51 | } 52 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 53 | } 54 | } 55 | 56 | // RegisterEchoService publish the given EchoService implementation on the server. 57 | func RegisterEchoService(srv *rpc.Server, x EchoService) error { 58 | if err := srv.RegisterName("EchoService", x); err != nil { 59 | return err 60 | } 61 | return nil 62 | } 63 | 64 | // NewEchoServiceServer returns a new EchoService Server. 65 | func NewEchoServiceServer(x EchoService) *rpc.Server { 66 | srv := rpc.NewServer() 67 | if err := srv.RegisterName("EchoService", x); err != nil { 68 | log.Fatal(err) 69 | } 70 | return srv 71 | } 72 | 73 | // ListenAndServeEchoService listen announces on the local network address laddr 74 | // and serves the given EchoService implementation. 75 | func ListenAndServeEchoService(network, addr string, x EchoService) error { 76 | lis, err := net.Listen(network, addr) 77 | if err != nil { 78 | return err 79 | } 80 | defer lis.Close() 81 | 82 | srv := rpc.NewServer() 83 | if err := srv.RegisterName("EchoService", x); err != nil { 84 | return err 85 | } 86 | 87 | for { 88 | conn, err := lis.Accept() 89 | if err != nil { 90 | log.Fatalf("lis.Accept(): %v\n", err) 91 | } 92 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 93 | } 94 | } 95 | 96 | // ServeEchoService serves the given EchoService implementation. 97 | func ServeEchoService(conn io.ReadWriteCloser, x EchoService) { 98 | srv := rpc.NewServer() 99 | if err := srv.RegisterName("EchoService", x); err != nil { 100 | log.Fatal(err) 101 | } 102 | srv.ServeCodec(protorpc.NewServerCodec(conn)) 103 | } 104 | 105 | type EchoServiceClient struct { 106 | *rpc.Client 107 | } 108 | 109 | // NewEchoServiceClient returns a EchoService stub to handle 110 | // requests to the set of EchoService at the other end of the connection. 111 | func NewEchoServiceClient(conn io.ReadWriteCloser) *EchoServiceClient { 112 | c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn)) 113 | return &EchoServiceClient{c} 114 | } 115 | 116 | func (c *EchoServiceClient) Echo(in *Message) (out *Message, err error) { 117 | if in == nil { 118 | in = new(Message) 119 | } 120 | 121 | type Validator interface { 122 | Validate() error 123 | } 124 | if x, ok := proto.Message(in).(Validator); ok { 125 | if err := x.Validate(); err != nil { 126 | return nil, err 127 | } 128 | } 129 | 130 | out = new(Message) 131 | if err = c.Call("EchoService.Echo", in, out); err != nil { 132 | return nil, err 133 | } 134 | 135 | if x, ok := proto.Message(out).(Validator); ok { 136 | if err := x.Validate(); err != nil { 137 | return out, err 138 | } 139 | } 140 | 141 | return out, nil 142 | } 143 | 144 | func (c *EchoServiceClient) AsyncEcho(in *Message, out *Message, done chan *rpc.Call) *rpc.Call { 145 | if in == nil { 146 | in = new(Message) 147 | } 148 | return c.Go( 149 | "EchoService.Echo", 150 | in, out, 151 | done, 152 | ) 153 | } 154 | 155 | // DialEchoService connects to an EchoService at the specified network address. 156 | func DialEchoService(network, addr string) (*EchoServiceClient, error) { 157 | c, err := protorpc.Dial(network, addr) 158 | if err != nil { 159 | return nil, err 160 | } 161 | return &EchoServiceClient{c}, nil 162 | } 163 | 164 | // DialEchoServiceTimeout connects to an EchoService at the specified network address. 165 | func DialEchoServiceTimeout(network, addr string, timeout time.Duration) (*EchoServiceClient, error) { 166 | c, err := protorpc.DialTimeout(network, addr, timeout) 167 | if err != nil { 168 | return nil, err 169 | } 170 | return &EchoServiceClient{c}, nil 171 | } 172 | -------------------------------------------------------------------------------- /examples/proto3.pb/proto3.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package proto3_proto; 8 | 9 | message Message { 10 | enum Humour { 11 | UNKNOWN = 0; 12 | PUNS = 1; 13 | SLAPSTICK = 2; 14 | BILL_BAILEY = 3; 15 | } 16 | 17 | string name = 1; 18 | Humour hilarity = 2; 19 | uint32 height_in_cm = 3; 20 | bytes data = 4; 21 | int64 result_count = 7; 22 | bool true_scotsman = 8; 23 | float score = 9; 24 | 25 | repeated uint64 key = 5; 26 | Nested nested = 6; 27 | 28 | map terrain = 10; 29 | } 30 | 31 | message Nested { 32 | string bunny = 1; 33 | } 34 | 35 | message MessageWithMap { 36 | map byte_mapping = 1; 37 | } 38 | 39 | service EchoService { 40 | rpc Echo(Message) returns (Message); 41 | } 42 | -------------------------------------------------------------------------------- /examples/proto3.pb/proto3_proto_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proto3_proto 6 | 7 | import ( 8 | "bytes" 9 | "encoding/gob" 10 | "log" 11 | "os" 12 | "reflect" 13 | "testing" 14 | "time" 15 | ) 16 | 17 | type tEchoService struct { 18 | private int 19 | } 20 | 21 | func (p *tEchoService) Echo(in *Message, out *Message) error { 22 | var buf bytes.Buffer 23 | if err := gob.NewEncoder(&buf).Encode(in); err != nil { 24 | return err 25 | } 26 | if err := gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(out); err != nil { 27 | return err 28 | } 29 | return nil 30 | } 31 | 32 | func TestMain(m *testing.M) { 33 | go func() { 34 | if err := ListenAndServeEchoService("tcp", "127.0.0.1:3000", new(tEchoService)); err != nil { 35 | log.Fatal(err) 36 | } 37 | }() 38 | time.Sleep(time.Second * 3) // wait for start the server 39 | os.Exit(m.Run()) 40 | } 41 | 42 | func TestEchoService(t *testing.T) { 43 | c, err := DialEchoService("tcp", "127.0.0.1:3000") 44 | if err != nil { 45 | t.Fatal(err) 46 | } 47 | defer c.Close() 48 | 49 | in := Message{ 50 | Name: "github.com/chai2010/protorpc", 51 | Hilarity: Message_PUNS, 52 | HeightInCm: 13, 53 | Data: []byte("bin data"), 54 | ResultCount: 2<<35 + 1, 55 | TrueScotsman: true, 56 | Score: 3.14, 57 | Key: []uint64{1, 1001}, 58 | Nested: &Nested{Bunny: "{{Bunny}}"}, 59 | Terrain: map[string]*Nested{ 60 | "A": &Nested{Bunny: "{{A}}"}, 61 | "B": &Nested{Bunny: "{{B}}"}, 62 | }, 63 | } 64 | 65 | out, err := c.Echo(&in) 66 | if err != nil { 67 | t.Fatal(err) 68 | } 69 | if !reflect.DeepEqual(&in, out) { 70 | t.Fatalf("not euqal, got = %v\n", &out) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /examples/service.pb/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2013 . All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PROTO_FILES=$(sort $(wildcard ./*.proto)) 6 | 7 | default: $(PROTO_FILES) Makefile 8 | go install github.com/golang/protobuf/protoc-gen-go 9 | go install github.com/chai2010/protorpc/protoc-gen-protorpc 10 | protoc --go_out=. ${PROTO_FILES} 11 | ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX= protoc --protorpc_out=. ${PROTO_FILES} 12 | go test 13 | 14 | clean: 15 | -------------------------------------------------------------------------------- /examples/service.pb/all_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package service 6 | 7 | import ( 8 | "log" 9 | "net" 10 | "net/rpc" 11 | "testing" 12 | 13 | "github.com/chai2010/protorpc" 14 | ) 15 | 16 | func init() { 17 | err := listenAndServeArithAndEchoService("tcp", "127.0.0.1:1984") 18 | if err != nil { 19 | log.Fatalf("listenAndServeArithAndEchoService: %v", err) 20 | } 21 | } 22 | 23 | func TestAll(t *testing.T) { 24 | conn, err := net.Dial("tcp", "127.0.0.1:1984") 25 | if err != nil { 26 | t.Fatalf(`net.Dial("tcp", "127.0.0.1:1984"): %v`, err) 27 | } 28 | client := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn)) 29 | defer client.Close() 30 | 31 | testArithClient(t, client) 32 | testEchoClient(t, client) 33 | 34 | arithStub := &ArithServiceClient{client} 35 | echoStub := &EchoServiceClient{client} 36 | 37 | testArithStub(t, arithStub) 38 | testEchoStub(t, echoStub) 39 | } 40 | 41 | func listenAndServeArithAndEchoService(network, addr string) error { 42 | clients, err := net.Listen(network, addr) 43 | if err != nil { 44 | return err 45 | } 46 | srv := rpc.NewServer() 47 | if err := RegisterArithService(srv, new(Arith)); err != nil { 48 | return err 49 | } 50 | if err := RegisterEchoService(srv, new(Echo)); err != nil { 51 | return err 52 | } 53 | go func() { 54 | for { 55 | conn, err := clients.Accept() 56 | if err != nil { 57 | log.Printf("clients.Accept(): %v\n", err) 58 | continue 59 | } 60 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 61 | } 62 | }() 63 | return nil 64 | } 65 | 66 | func testArithClient(t *testing.T, client *rpc.Client) { 67 | var args ArithRequest 68 | var reply ArithResponse 69 | var err error 70 | 71 | // Add 72 | args.A = 1 73 | args.B = 2 74 | if err = client.Call("ArithService.Add", &args, &reply); err != nil { 75 | t.Fatalf(`arith.Add: %v`, err) 76 | } 77 | if reply.C != 3 { 78 | t.Fatalf(`arith.Add: expected = %d, got = %d`, 3, reply.C) 79 | } 80 | 81 | // Mul 82 | args.A = 2 83 | args.B = 3 84 | if err = client.Call("ArithService.Mul", &args, &reply); err != nil { 85 | t.Fatalf(`arith.Mul: %v`, err) 86 | } 87 | if reply.C != 6 { 88 | t.Fatalf(`arith.Mul: expected = %d, got = %d`, 6, reply.C) 89 | } 90 | 91 | // Div 92 | args.A = 13 93 | args.B = 5 94 | if err = client.Call("ArithService.Div", &args, &reply); err != nil { 95 | t.Fatalf(`arith.Div: %v`, err) 96 | } 97 | if reply.C != 2 { 98 | t.Fatalf(`arith.Div: expected = %d, got = %d`, 2, reply.C) 99 | } 100 | 101 | // Div zero 102 | args.A = 1 103 | args.B = 0 104 | if err = client.Call("ArithService.Div", &args, &reply); err.Error() != "divide by zero" { 105 | t.Fatalf(`arith.Div: expected = "%s", got = "%s"`, "divide by zero", err.Error()) 106 | } 107 | 108 | // Error 109 | args.A = 1 110 | args.B = 2 111 | if err = client.Call("ArithService.Error", &args, &reply); err.Error() != "ArithError" { 112 | t.Fatalf(`arith.Error: expected = "%s", got = "%s"`, "ArithError", err.Error()) 113 | } 114 | } 115 | 116 | func testEchoClient(t *testing.T, client *rpc.Client) { 117 | var args EchoRequest 118 | var reply EchoResponse 119 | var err error 120 | 121 | // EchoService.Echo 122 | args.Msg = "Hello, Protobuf-RPC" 123 | if err = client.Call("EchoService.Echo", &args, &reply); err != nil { 124 | t.Fatalf(`echo.Echo: %v`, err) 125 | } 126 | if reply.Msg != args.Msg { 127 | t.Fatalf(`echo.Echo: expected = "%s", got = "%s"`, args.Msg, reply.Msg) 128 | } 129 | } 130 | 131 | func testArithStub(t *testing.T, stub *ArithServiceClient) { 132 | var args ArithRequest 133 | var reply *ArithResponse 134 | var err error 135 | 136 | // Add 137 | args.A = 1 138 | args.B = 2 139 | if reply, err = stub.Add(&args); err != nil { 140 | t.Fatalf(`stub.Add: %v`, err) 141 | } 142 | if reply.C != 3 { 143 | t.Fatalf(`stub.Add: expected = %d, got = %d`, 3, reply.C) 144 | } 145 | 146 | // Mul 147 | args.A = 2 148 | args.B = 3 149 | if reply, err = stub.Mul(&args); err != nil { 150 | t.Fatalf(`stub.Mul: %v`, err) 151 | } 152 | if reply.C != 6 { 153 | t.Fatalf(`stub.Mul: expected = %d, got = %d`, 6, reply.C) 154 | } 155 | 156 | // Div 157 | args.A = 13 158 | args.B = 5 159 | if reply, err = stub.Div(&args); err != nil { 160 | t.Fatalf(`stub.Div: %v`, err) 161 | } 162 | if reply.C != 2 { 163 | t.Fatalf(`stub.Div: expected = %d, got = %d`, 2, reply.C) 164 | } 165 | 166 | // Div zero 167 | args.A = 1 168 | args.B = 0 169 | if reply, err = stub.Div(&args); err.Error() != "divide by zero" { 170 | t.Fatalf(`stub.Div: expected = "%s", got = "%s"`, "divide by zero", err.Error()) 171 | } 172 | 173 | // Error 174 | args.A = 1 175 | args.B = 2 176 | if reply, err = stub.Error(&args); err.Error() != "ArithError" { 177 | t.Fatalf(`stub.Error: expected = "%s", got = "%s"`, "ArithError", err.Error()) 178 | } 179 | } 180 | func testEchoStub(t *testing.T, stub *EchoServiceClient) { 181 | var args EchoRequest 182 | var reply *EchoResponse 183 | var err error 184 | 185 | // EchoService.Echo 186 | args.Msg = "Hello, Protobuf-RPC" 187 | if reply, err = stub.Echo(&args); err != nil { 188 | t.Fatalf(`stub.Echo: %v`, err) 189 | } 190 | if reply.Msg != args.Msg { 191 | t.Fatalf(`stub.Echo: expected = "%s", got = "%s"`, args.Msg, reply.Msg) 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /examples/service.pb/arith.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package service 6 | 7 | import ( 8 | "errors" 9 | ) 10 | 11 | type Arith int 12 | 13 | func (t *Arith) Add(args *ArithRequest, reply *ArithResponse) error { 14 | reply.C = args.A + args.B 15 | return nil 16 | } 17 | 18 | func (t *Arith) Mul(args *ArithRequest, reply *ArithResponse) error { 19 | reply.C = args.A * args.B 20 | return nil 21 | } 22 | 23 | func (t *Arith) Div(args *ArithRequest, reply *ArithResponse) error { 24 | if args.B == 0 { 25 | return errors.New("divide by zero") 26 | } 27 | reply.C = args.A / args.B 28 | return nil 29 | } 30 | 31 | func (t *Arith) Error(args *ArithRequest, reply *ArithResponse) error { 32 | return errors.New("ArithError") 33 | } 34 | -------------------------------------------------------------------------------- /examples/service.pb/arith.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: arith.proto 3 | 4 | /* 5 | Package service is a generated protocol buffer package. 6 | 7 | It is generated from these files: 8 | arith.proto 9 | echo.proto 10 | 11 | It has these top-level messages: 12 | ArithRequest 13 | ArithResponse 14 | EchoRequest 15 | EchoResponse 16 | */ 17 | package service 18 | 19 | import proto "github.com/golang/protobuf/proto" 20 | import fmt "fmt" 21 | import math "math" 22 | 23 | // Reference imports to suppress errors if they are not otherwise used. 24 | var _ = proto.Marshal 25 | var _ = fmt.Errorf 26 | var _ = math.Inf 27 | 28 | // This is a compile-time assertion to ensure that this generated file 29 | // is compatible with the proto package it is being compiled against. 30 | // A compilation error at this line likely means your copy of the 31 | // proto package needs to be updated. 32 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 33 | 34 | type ArithRequest struct { 35 | A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"` 36 | B int32 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"` 37 | } 38 | 39 | func (m *ArithRequest) Reset() { *m = ArithRequest{} } 40 | func (m *ArithRequest) String() string { return proto.CompactTextString(m) } 41 | func (*ArithRequest) ProtoMessage() {} 42 | func (*ArithRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 43 | 44 | func (m *ArithRequest) GetA() int32 { 45 | if m != nil { 46 | return m.A 47 | } 48 | return 0 49 | } 50 | 51 | func (m *ArithRequest) GetB() int32 { 52 | if m != nil { 53 | return m.B 54 | } 55 | return 0 56 | } 57 | 58 | type ArithResponse struct { 59 | C int32 `protobuf:"varint,1,opt,name=c" json:"c,omitempty"` 60 | } 61 | 62 | func (m *ArithResponse) Reset() { *m = ArithResponse{} } 63 | func (m *ArithResponse) String() string { return proto.CompactTextString(m) } 64 | func (*ArithResponse) ProtoMessage() {} 65 | func (*ArithResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } 66 | 67 | func (m *ArithResponse) GetC() int32 { 68 | if m != nil { 69 | return m.C 70 | } 71 | return 0 72 | } 73 | 74 | func init() { 75 | proto.RegisterType((*ArithRequest)(nil), "service.ArithRequest") 76 | proto.RegisterType((*ArithResponse)(nil), "service.ArithResponse") 77 | } 78 | 79 | func init() { proto.RegisterFile("arith.proto", fileDescriptor0) } 80 | 81 | var fileDescriptor0 = []byte{ 82 | // 159 bytes of a gzipped FileDescriptorProto 83 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0x2c, 0xca, 0x2c, 84 | 0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 85 | 0x55, 0xd2, 0xe2, 0xe2, 0x71, 0x04, 0x89, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0xf1, 86 | 0x70, 0x31, 0x26, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x31, 0x26, 0x82, 0x78, 0x49, 0x12, 87 | 0x4c, 0x10, 0x5e, 0x92, 0x92, 0x2c, 0x17, 0x2f, 0x54, 0x6d, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0x2a, 88 | 0x48, 0x3a, 0x19, 0xa6, 0x38, 0xd9, 0xe8, 0x05, 0x23, 0xd4, 0xac, 0x60, 0x88, 0xd9, 0x42, 0x26, 89 | 0x5c, 0xcc, 0x89, 0x29, 0x29, 0x42, 0xa2, 0x7a, 0x50, 0xcb, 0xf4, 0x90, 0x6d, 0x92, 0x12, 0x43, 90 | 0x17, 0x86, 0x1a, 0x6a, 0xc2, 0xc5, 0x9c, 0x5b, 0x9a, 0x43, 0x86, 0xae, 0x94, 0xcc, 0x32, 0x52, 91 | 0x75, 0x99, 0x71, 0xb1, 0xa6, 0x16, 0x15, 0xe5, 0x17, 0x91, 0xa8, 0x2f, 0x89, 0x0d, 0x1c, 0x8a, 92 | 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x62, 0xfd, 0xbd, 0x54, 0x01, 0x00, 0x00, 93 | } 94 | -------------------------------------------------------------------------------- /examples/service.pb/arith.pb.protorpc.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-protorpc. DO NOT EDIT. 2 | // 3 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin 4 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc 5 | // 6 | // source: arith.proto 7 | 8 | package service 9 | 10 | import ( 11 | "fmt" 12 | "io" 13 | "log" 14 | "net" 15 | "net/rpc" 16 | "time" 17 | 18 | "github.com/chai2010/protorpc" 19 | "github.com/golang/protobuf/proto" 20 | ) 21 | 22 | var ( 23 | _ = fmt.Sprint 24 | _ = io.Reader(nil) 25 | _ = log.Print 26 | _ = net.Addr(nil) 27 | _ = rpc.Call{} 28 | _ = time.Second 29 | 30 | _ = proto.String 31 | _ = protorpc.Dial 32 | ) 33 | 34 | type ArithService interface { 35 | Add(in *ArithRequest, out *ArithResponse) error 36 | Mul(in *ArithRequest, out *ArithResponse) error 37 | Div(in *ArithRequest, out *ArithResponse) error 38 | Error(in *ArithRequest, out *ArithResponse) error 39 | } 40 | 41 | // AcceptArithServiceClient accepts connections on the listener and serves requests 42 | // for each incoming connection. Accept blocks; the caller typically 43 | // invokes it in a go statement. 44 | func AcceptArithServiceClient(lis net.Listener, x ArithService) { 45 | srv := rpc.NewServer() 46 | if err := srv.RegisterName("ArithService", x); err != nil { 47 | log.Fatal(err) 48 | } 49 | 50 | for { 51 | conn, err := lis.Accept() 52 | if err != nil { 53 | log.Fatalf("lis.Accept(): %v\n", err) 54 | } 55 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 56 | } 57 | } 58 | 59 | // RegisterArithService publish the given ArithService implementation on the server. 60 | func RegisterArithService(srv *rpc.Server, x ArithService) error { 61 | if err := srv.RegisterName("ArithService", x); err != nil { 62 | return err 63 | } 64 | return nil 65 | } 66 | 67 | // NewArithServiceServer returns a new ArithService Server. 68 | func NewArithServiceServer(x ArithService) *rpc.Server { 69 | srv := rpc.NewServer() 70 | if err := srv.RegisterName("ArithService", x); err != nil { 71 | log.Fatal(err) 72 | } 73 | return srv 74 | } 75 | 76 | // ListenAndServeArithService listen announces on the local network address laddr 77 | // and serves the given ArithService implementation. 78 | func ListenAndServeArithService(network, addr string, x ArithService) error { 79 | lis, err := net.Listen(network, addr) 80 | if err != nil { 81 | return err 82 | } 83 | defer lis.Close() 84 | 85 | srv := rpc.NewServer() 86 | if err := srv.RegisterName("ArithService", x); err != nil { 87 | return err 88 | } 89 | 90 | for { 91 | conn, err := lis.Accept() 92 | if err != nil { 93 | log.Fatalf("lis.Accept(): %v\n", err) 94 | } 95 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 96 | } 97 | } 98 | 99 | // ServeArithService serves the given ArithService implementation. 100 | func ServeArithService(conn io.ReadWriteCloser, x ArithService) { 101 | srv := rpc.NewServer() 102 | if err := srv.RegisterName("ArithService", x); err != nil { 103 | log.Fatal(err) 104 | } 105 | srv.ServeCodec(protorpc.NewServerCodec(conn)) 106 | } 107 | 108 | type ArithServiceClient struct { 109 | *rpc.Client 110 | } 111 | 112 | // NewArithServiceClient returns a ArithService stub to handle 113 | // requests to the set of ArithService at the other end of the connection. 114 | func NewArithServiceClient(conn io.ReadWriteCloser) *ArithServiceClient { 115 | c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn)) 116 | return &ArithServiceClient{c} 117 | } 118 | 119 | func (c *ArithServiceClient) Add(in *ArithRequest) (out *ArithResponse, err error) { 120 | if in == nil { 121 | in = new(ArithRequest) 122 | } 123 | 124 | type Validator interface { 125 | Validate() error 126 | } 127 | if x, ok := proto.Message(in).(Validator); ok { 128 | if err := x.Validate(); err != nil { 129 | return nil, err 130 | } 131 | } 132 | 133 | out = new(ArithResponse) 134 | if err = c.Call("ArithService.Add", in, out); err != nil { 135 | return nil, err 136 | } 137 | 138 | if x, ok := proto.Message(out).(Validator); ok { 139 | if err := x.Validate(); err != nil { 140 | return out, err 141 | } 142 | } 143 | 144 | return out, nil 145 | } 146 | 147 | func (c *ArithServiceClient) AsyncAdd(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 148 | if in == nil { 149 | in = new(ArithRequest) 150 | } 151 | return c.Go( 152 | "ArithService.Add", 153 | in, out, 154 | done, 155 | ) 156 | } 157 | 158 | func (c *ArithServiceClient) Mul(in *ArithRequest) (out *ArithResponse, err error) { 159 | if in == nil { 160 | in = new(ArithRequest) 161 | } 162 | 163 | type Validator interface { 164 | Validate() error 165 | } 166 | if x, ok := proto.Message(in).(Validator); ok { 167 | if err := x.Validate(); err != nil { 168 | return nil, err 169 | } 170 | } 171 | 172 | out = new(ArithResponse) 173 | if err = c.Call("ArithService.Mul", in, out); err != nil { 174 | return nil, err 175 | } 176 | 177 | if x, ok := proto.Message(out).(Validator); ok { 178 | if err := x.Validate(); err != nil { 179 | return out, err 180 | } 181 | } 182 | 183 | return out, nil 184 | } 185 | 186 | func (c *ArithServiceClient) AsyncMul(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 187 | if in == nil { 188 | in = new(ArithRequest) 189 | } 190 | return c.Go( 191 | "ArithService.Mul", 192 | in, out, 193 | done, 194 | ) 195 | } 196 | 197 | func (c *ArithServiceClient) Div(in *ArithRequest) (out *ArithResponse, err error) { 198 | if in == nil { 199 | in = new(ArithRequest) 200 | } 201 | 202 | type Validator interface { 203 | Validate() error 204 | } 205 | if x, ok := proto.Message(in).(Validator); ok { 206 | if err := x.Validate(); err != nil { 207 | return nil, err 208 | } 209 | } 210 | 211 | out = new(ArithResponse) 212 | if err = c.Call("ArithService.Div", in, out); err != nil { 213 | return nil, err 214 | } 215 | 216 | if x, ok := proto.Message(out).(Validator); ok { 217 | if err := x.Validate(); err != nil { 218 | return out, err 219 | } 220 | } 221 | 222 | return out, nil 223 | } 224 | 225 | func (c *ArithServiceClient) AsyncDiv(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 226 | if in == nil { 227 | in = new(ArithRequest) 228 | } 229 | return c.Go( 230 | "ArithService.Div", 231 | in, out, 232 | done, 233 | ) 234 | } 235 | 236 | func (c *ArithServiceClient) Error(in *ArithRequest) (out *ArithResponse, err error) { 237 | if in == nil { 238 | in = new(ArithRequest) 239 | } 240 | 241 | type Validator interface { 242 | Validate() error 243 | } 244 | if x, ok := proto.Message(in).(Validator); ok { 245 | if err := x.Validate(); err != nil { 246 | return nil, err 247 | } 248 | } 249 | 250 | out = new(ArithResponse) 251 | if err = c.Call("ArithService.Error", in, out); err != nil { 252 | return nil, err 253 | } 254 | 255 | if x, ok := proto.Message(out).(Validator); ok { 256 | if err := x.Validate(); err != nil { 257 | return out, err 258 | } 259 | } 260 | 261 | return out, nil 262 | } 263 | 264 | func (c *ArithServiceClient) AsyncError(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 265 | if in == nil { 266 | in = new(ArithRequest) 267 | } 268 | return c.Go( 269 | "ArithService.Error", 270 | in, out, 271 | done, 272 | ) 273 | } 274 | 275 | // DialArithService connects to an ArithService at the specified network address. 276 | func DialArithService(network, addr string) (*ArithServiceClient, error) { 277 | c, err := protorpc.Dial(network, addr) 278 | if err != nil { 279 | return nil, err 280 | } 281 | return &ArithServiceClient{c}, nil 282 | } 283 | 284 | // DialArithServiceTimeout connects to an ArithService at the specified network address. 285 | func DialArithServiceTimeout(network, addr string, timeout time.Duration) (*ArithServiceClient, error) { 286 | c, err := protorpc.DialTimeout(network, addr, timeout) 287 | if err != nil { 288 | return nil, err 289 | } 290 | return &ArithServiceClient{c}, nil 291 | } 292 | -------------------------------------------------------------------------------- /examples/service.pb/arith.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package service; 8 | 9 | message ArithRequest { 10 | int32 a = 1; 11 | int32 b = 2; 12 | } 13 | 14 | message ArithResponse { 15 | int32 c = 1; 16 | } 17 | 18 | service ArithService { 19 | rpc add (ArithRequest) returns (ArithResponse); 20 | rpc mul (ArithRequest) returns (ArithResponse); 21 | rpc div (ArithRequest) returns (ArithResponse); 22 | rpc error (ArithRequest) returns (ArithResponse); 23 | } 24 | -------------------------------------------------------------------------------- /examples/service.pb/arith_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package service 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "sync" 11 | ) 12 | 13 | var ( 14 | arithHost = "127.0.0.1" 15 | arithPort = 2010 16 | 17 | onceArith sync.Once 18 | ) 19 | 20 | func setupArithServer() { 21 | var wg sync.WaitGroup 22 | wg.Add(1) 23 | defer wg.Wait() 24 | 25 | go func() { 26 | wg.Done() 27 | 28 | addr := fmt.Sprintf("127.0.0.1:%d", arithPort) 29 | err := ListenAndServeArithService("tcp", addr, new(Arith)) 30 | if err != nil { 31 | log.Fatalf("ListenAndServeArithService: %v", err) 32 | } 33 | }() 34 | } 35 | -------------------------------------------------------------------------------- /examples/service.pb/echo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package service 6 | 7 | type Echo int 8 | 9 | func (t *Echo) Echo(args *EchoRequest, reply *EchoResponse) error { 10 | reply.Msg = args.Msg 11 | return nil 12 | } 13 | 14 | func (t *Echo) EchoTwice(args *EchoRequest, reply *EchoResponse) error { 15 | reply.Msg = args.Msg + args.Msg 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /examples/service.pb/echo.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: echo.proto 3 | 4 | package service 5 | 6 | import proto "github.com/golang/protobuf/proto" 7 | import fmt "fmt" 8 | import math "math" 9 | 10 | // Reference imports to suppress errors if they are not otherwise used. 11 | var _ = proto.Marshal 12 | var _ = fmt.Errorf 13 | var _ = math.Inf 14 | 15 | type EchoRequest struct { 16 | Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"` 17 | } 18 | 19 | func (m *EchoRequest) Reset() { *m = EchoRequest{} } 20 | func (m *EchoRequest) String() string { return proto.CompactTextString(m) } 21 | func (*EchoRequest) ProtoMessage() {} 22 | func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } 23 | 24 | func (m *EchoRequest) GetMsg() string { 25 | if m != nil { 26 | return m.Msg 27 | } 28 | return "" 29 | } 30 | 31 | type EchoResponse struct { 32 | Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"` 33 | } 34 | 35 | func (m *EchoResponse) Reset() { *m = EchoResponse{} } 36 | func (m *EchoResponse) String() string { return proto.CompactTextString(m) } 37 | func (*EchoResponse) ProtoMessage() {} 38 | func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } 39 | 40 | func (m *EchoResponse) GetMsg() string { 41 | if m != nil { 42 | return m.Msg 43 | } 44 | return "" 45 | } 46 | 47 | func init() { 48 | proto.RegisterType((*EchoRequest)(nil), "service.EchoRequest") 49 | proto.RegisterType((*EchoResponse)(nil), "service.EchoResponse") 50 | } 51 | 52 | func init() { proto.RegisterFile("echo.proto", fileDescriptor1) } 53 | 54 | var fileDescriptor1 = []byte{ 55 | // 134 bytes of a gzipped FileDescriptorProto 56 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8, 57 | 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x55, 58 | 0x92, 0xe7, 0xe2, 0x76, 0x4d, 0xce, 0xc8, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12, 59 | 0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x95, 0x14, 60 | 0xb8, 0x78, 0x20, 0x0a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x31, 0x55, 0x18, 0xd5, 0x40, 0x8c, 61 | 0x08, 0x86, 0x98, 0x28, 0x64, 0xcc, 0xc5, 0x02, 0xe2, 0x0a, 0x89, 0xe8, 0x41, 0xed, 0xd0, 0x43, 62 | 0xb2, 0x40, 0x4a, 0x14, 0x4d, 0x14, 0x6a, 0xaa, 0x05, 0x17, 0x27, 0x88, 0x1f, 0x52, 0x0e, 0x32, 63 | 0x81, 0x14, 0x9d, 0x49, 0x6c, 0x60, 0x0f, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc1, 64 | 0xd4, 0xbd, 0xde, 0x00, 0x00, 0x00, 65 | } 66 | -------------------------------------------------------------------------------- /examples/service.pb/echo.pb.protorpc.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-protorpc. DO NOT EDIT. 2 | // 3 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin 4 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc 5 | // 6 | // source: echo.proto 7 | 8 | package service 9 | 10 | import ( 11 | "fmt" 12 | "io" 13 | "log" 14 | "net" 15 | "net/rpc" 16 | "time" 17 | 18 | "github.com/chai2010/protorpc" 19 | "github.com/golang/protobuf/proto" 20 | ) 21 | 22 | var ( 23 | _ = fmt.Sprint 24 | _ = io.Reader(nil) 25 | _ = log.Print 26 | _ = net.Addr(nil) 27 | _ = rpc.Call{} 28 | _ = time.Second 29 | 30 | _ = proto.String 31 | _ = protorpc.Dial 32 | ) 33 | 34 | type EchoService interface { 35 | Echo(in *EchoRequest, out *EchoResponse) error 36 | EchoTwice(in *EchoRequest, out *EchoResponse) error 37 | } 38 | 39 | // AcceptEchoServiceClient accepts connections on the listener and serves requests 40 | // for each incoming connection. Accept blocks; the caller typically 41 | // invokes it in a go statement. 42 | func AcceptEchoServiceClient(lis net.Listener, x EchoService) { 43 | srv := rpc.NewServer() 44 | if err := srv.RegisterName("EchoService", x); err != nil { 45 | log.Fatal(err) 46 | } 47 | 48 | for { 49 | conn, err := lis.Accept() 50 | if err != nil { 51 | log.Fatalf("lis.Accept(): %v\n", err) 52 | } 53 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 54 | } 55 | } 56 | 57 | // RegisterEchoService publish the given EchoService implementation on the server. 58 | func RegisterEchoService(srv *rpc.Server, x EchoService) error { 59 | if err := srv.RegisterName("EchoService", x); err != nil { 60 | return err 61 | } 62 | return nil 63 | } 64 | 65 | // NewEchoServiceServer returns a new EchoService Server. 66 | func NewEchoServiceServer(x EchoService) *rpc.Server { 67 | srv := rpc.NewServer() 68 | if err := srv.RegisterName("EchoService", x); err != nil { 69 | log.Fatal(err) 70 | } 71 | return srv 72 | } 73 | 74 | // ListenAndServeEchoService listen announces on the local network address laddr 75 | // and serves the given EchoService implementation. 76 | func ListenAndServeEchoService(network, addr string, x EchoService) error { 77 | lis, err := net.Listen(network, addr) 78 | if err != nil { 79 | return err 80 | } 81 | defer lis.Close() 82 | 83 | srv := rpc.NewServer() 84 | if err := srv.RegisterName("EchoService", x); err != nil { 85 | return err 86 | } 87 | 88 | for { 89 | conn, err := lis.Accept() 90 | if err != nil { 91 | log.Fatalf("lis.Accept(): %v\n", err) 92 | } 93 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 94 | } 95 | } 96 | 97 | // ServeEchoService serves the given EchoService implementation. 98 | func ServeEchoService(conn io.ReadWriteCloser, x EchoService) { 99 | srv := rpc.NewServer() 100 | if err := srv.RegisterName("EchoService", x); err != nil { 101 | log.Fatal(err) 102 | } 103 | srv.ServeCodec(protorpc.NewServerCodec(conn)) 104 | } 105 | 106 | type EchoServiceClient struct { 107 | *rpc.Client 108 | } 109 | 110 | // NewEchoServiceClient returns a EchoService stub to handle 111 | // requests to the set of EchoService at the other end of the connection. 112 | func NewEchoServiceClient(conn io.ReadWriteCloser) *EchoServiceClient { 113 | c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn)) 114 | return &EchoServiceClient{c} 115 | } 116 | 117 | func (c *EchoServiceClient) Echo(in *EchoRequest) (out *EchoResponse, err error) { 118 | if in == nil { 119 | in = new(EchoRequest) 120 | } 121 | 122 | type Validator interface { 123 | Validate() error 124 | } 125 | if x, ok := proto.Message(in).(Validator); ok { 126 | if err := x.Validate(); err != nil { 127 | return nil, err 128 | } 129 | } 130 | 131 | out = new(EchoResponse) 132 | if err = c.Call("EchoService.Echo", in, out); err != nil { 133 | return nil, err 134 | } 135 | 136 | if x, ok := proto.Message(out).(Validator); ok { 137 | if err := x.Validate(); err != nil { 138 | return out, err 139 | } 140 | } 141 | 142 | return out, nil 143 | } 144 | 145 | func (c *EchoServiceClient) AsyncEcho(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call { 146 | if in == nil { 147 | in = new(EchoRequest) 148 | } 149 | return c.Go( 150 | "EchoService.Echo", 151 | in, out, 152 | done, 153 | ) 154 | } 155 | 156 | func (c *EchoServiceClient) EchoTwice(in *EchoRequest) (out *EchoResponse, err error) { 157 | if in == nil { 158 | in = new(EchoRequest) 159 | } 160 | 161 | type Validator interface { 162 | Validate() error 163 | } 164 | if x, ok := proto.Message(in).(Validator); ok { 165 | if err := x.Validate(); err != nil { 166 | return nil, err 167 | } 168 | } 169 | 170 | out = new(EchoResponse) 171 | if err = c.Call("EchoService.EchoTwice", in, out); err != nil { 172 | return nil, err 173 | } 174 | 175 | if x, ok := proto.Message(out).(Validator); ok { 176 | if err := x.Validate(); err != nil { 177 | return out, err 178 | } 179 | } 180 | 181 | return out, nil 182 | } 183 | 184 | func (c *EchoServiceClient) AsyncEchoTwice(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call { 185 | if in == nil { 186 | in = new(EchoRequest) 187 | } 188 | return c.Go( 189 | "EchoService.EchoTwice", 190 | in, out, 191 | done, 192 | ) 193 | } 194 | 195 | // DialEchoService connects to an EchoService at the specified network address. 196 | func DialEchoService(network, addr string) (*EchoServiceClient, error) { 197 | c, err := protorpc.Dial(network, addr) 198 | if err != nil { 199 | return nil, err 200 | } 201 | return &EchoServiceClient{c}, nil 202 | } 203 | 204 | // DialEchoServiceTimeout connects to an EchoService at the specified network address. 205 | func DialEchoServiceTimeout(network, addr string, timeout time.Duration) (*EchoServiceClient, error) { 206 | c, err := protorpc.DialTimeout(network, addr, timeout) 207 | if err != nil { 208 | return nil, err 209 | } 210 | return &EchoServiceClient{c}, nil 211 | } 212 | -------------------------------------------------------------------------------- /examples/service.pb/echo.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package service; 8 | 9 | message EchoRequest { 10 | string msg = 1; 11 | } 12 | 13 | message EchoResponse { 14 | string msg = 1; 15 | } 16 | 17 | service EchoService { 18 | rpc Echo (EchoRequest) returns (EchoResponse); 19 | rpc EchoTwice (EchoRequest) returns (EchoResponse); 20 | } 21 | -------------------------------------------------------------------------------- /examples/service.pb/echo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package service 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "net/rpc" 11 | "sync" 12 | "testing" 13 | "unicode/utf8" 14 | ) 15 | 16 | var ( 17 | echoHost = "127.0.0.1" 18 | echoPort = 2015 19 | 20 | echoRequest = "Hello, new gopher!" 21 | echoResponse = echoRequest + echoRequest 22 | echoMassiveRequest = makeMassive("Hello, 世界.") 23 | echoMassiveResponse = echoMassiveRequest + echoMassiveRequest 24 | 25 | onceEcho sync.Once 26 | ) 27 | 28 | func makeMassive(args string) string { 29 | runeLen := utf8.RuneCountInString(args) 30 | runeBuf := make([]rune, runeLen*1024*100) 31 | for i := 0; i < 1024*100; i++ { 32 | offset := i * runeLen 33 | j := 0 34 | for _, r := range args { 35 | runeBuf[offset+j] = r 36 | j++ 37 | } 38 | } 39 | return string(runeBuf) 40 | } 41 | 42 | func setupEchoServer() { 43 | var wg sync.WaitGroup 44 | wg.Add(1) 45 | defer wg.Wait() 46 | 47 | go func() { 48 | wg.Done() 49 | 50 | addr := fmt.Sprintf("127.0.0.1:%d", echoPort) 51 | err := ListenAndServeEchoService("tcp", addr, new(Echo)) 52 | if err != nil { 53 | log.Fatalf("ListenAndServeEchoService: %v", err) 54 | } 55 | }() 56 | } 57 | 58 | func TestEchoService(t *testing.T) { 59 | onceEcho.Do(setupEchoServer) 60 | 61 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 62 | c, err := DialEchoService("tcp", addr) 63 | if err != nil { 64 | t.Fatalf( 65 | `net.Dial("tcp", "%s:%d"): %v`, 66 | echoHost, echoPort, 67 | err, 68 | ) 69 | } 70 | defer c.Close() 71 | 72 | testEchoService(t, c.Client) 73 | } 74 | 75 | func testEchoService(t *testing.T, client *rpc.Client) { 76 | var args EchoRequest 77 | var reply EchoResponse 78 | var err error 79 | 80 | // EchoService.EchoTwice 81 | args.Msg = echoRequest 82 | err = client.Call("EchoService.EchoTwice", &args, &reply) 83 | if err != nil { 84 | t.Fatalf(`EchoService.EchoTwice: %v`, err) 85 | } 86 | if reply.Msg != echoResponse { 87 | t.Fatalf( 88 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 89 | echoResponse, reply.Msg, 90 | ) 91 | } 92 | 93 | // EchoService.EchoTwice (Massive) 94 | args.Msg = echoMassiveRequest 95 | err = client.Call("EchoService.EchoTwice", &args, &reply) 96 | if err != nil { 97 | t.Fatalf(`EchoService.EchoTwice: %v`, err) 98 | } 99 | if reply.Msg != echoMassiveResponse { 100 | got := reply.Msg 101 | if len(got) > 8 { 102 | got = got[:8] + "..." 103 | } 104 | t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 105 | len(reply.Msg), got, 106 | ) 107 | } 108 | } 109 | 110 | func TestClientSyncEcho(t *testing.T) { 111 | onceEcho.Do(setupEchoServer) 112 | 113 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 114 | echoClient, err := DialEchoService("tcp", addr) 115 | if err != nil { 116 | t.Fatalf( 117 | `net.Dial("tcp", "%s:%d"): %v`, 118 | echoHost, echoPort, 119 | err, 120 | ) 121 | } 122 | defer echoClient.Close() 123 | 124 | var args EchoRequest 125 | var reply *EchoResponse 126 | 127 | // EchoService.EchoTwice 128 | args.Msg = "abc" 129 | reply, err = echoClient.EchoTwice(&args) 130 | if err != nil { 131 | t.Fatalf(`EchoService.EchoTwice: %v`, err) 132 | } 133 | if reply.Msg != args.Msg+args.Msg { 134 | t.Fatalf( 135 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 136 | args.Msg+args.Msg, reply.Msg, 137 | ) 138 | } 139 | 140 | // EchoService.EchoTwice 141 | args.Msg = "你好, 世界" 142 | reply, err = echoClient.EchoTwice(&args) 143 | if err != nil { 144 | t.Fatalf(`EchoService.EchoTwice: %v`, err) 145 | } 146 | if reply.Msg != args.Msg+args.Msg { 147 | t.Fatalf( 148 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 149 | args.Msg+args.Msg, reply.Msg, 150 | ) 151 | } 152 | } 153 | 154 | func TestClientSyncMassive(t *testing.T) { 155 | onceEcho.Do(setupEchoServer) 156 | 157 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 158 | echoClient, err := DialEchoService("tcp", addr) 159 | if err != nil { 160 | t.Fatalf( 161 | `net.Dial("tcp", "%s:%d"): %v`, 162 | echoHost, echoPort, 163 | err, 164 | ) 165 | } 166 | defer echoClient.Close() 167 | 168 | var args EchoRequest 169 | var reply *EchoResponse 170 | 171 | // EchoService.EchoTwice 172 | args.Msg = echoMassiveRequest + "abc" 173 | reply, err = echoClient.EchoTwice(&args) 174 | if err != nil { 175 | t.Fatalf(`EchoService.EchoTwice: %v`, err) 176 | } 177 | if reply.Msg != args.Msg+args.Msg { 178 | got := reply.Msg 179 | if len(got) > 8 { 180 | got = got[:8] + "..." 181 | } 182 | t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 183 | len(reply.Msg), got, 184 | ) 185 | } 186 | 187 | // EchoService.EchoTwice 188 | args.Msg = echoMassiveRequest + "你好, 世界" 189 | reply, err = echoClient.EchoTwice(&args) 190 | if err != nil { 191 | t.Fatalf(`EchoService.EchoTwice: %v`, err) 192 | } 193 | if reply.Msg != args.Msg+args.Msg { 194 | got := reply.Msg 195 | if len(got) > 8 { 196 | got = got[:8] + "..." 197 | } 198 | t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 199 | len(reply.Msg), got, 200 | ) 201 | } 202 | } 203 | 204 | func TestClientAsyncEcho(t *testing.T) { 205 | onceEcho.Do(setupEchoServer) 206 | 207 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 208 | client, err := DialEchoService("tcp", addr) 209 | if err != nil { 210 | t.Fatalf( 211 | `net.Dial("tcp", "%s:%d"): %v`, 212 | echoHost, echoPort, 213 | err, 214 | ) 215 | } 216 | defer client.Close() 217 | 218 | var args EchoRequest 219 | var reply EchoResponse 220 | 221 | // EchoService.EchoTwice 222 | args.Msg = echoRequest 223 | call := client.Go("EchoService.EchoTwice", &args, &reply, nil) 224 | 225 | call = <-call.Done 226 | if call.Error != nil { 227 | t.Fatalf(`EchoService.EchoTwice: %v`, call.Error) 228 | } 229 | if call.Reply.(*EchoResponse).Msg != echoResponse { 230 | t.Fatalf( 231 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 232 | echoResponse, call.Reply.(*EchoResponse).Msg, 233 | ) 234 | } 235 | } 236 | 237 | func TestClientAsyncEchoBatches(t *testing.T) { 238 | onceEcho.Do(setupEchoServer) 239 | 240 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 241 | client, err := DialEchoService("tcp", addr) 242 | if err != nil { 243 | t.Fatalf( 244 | `net.Dial("tcp", "%s:%d"): %v`, 245 | echoHost, echoPort, 246 | err, 247 | ) 248 | } 249 | defer client.Close() 250 | 251 | var args1 EchoRequest 252 | var reply1 EchoResponse 253 | var args2 EchoRequest 254 | var reply2 EchoResponse 255 | var args3 EchoRequest 256 | var reply3 EchoResponse 257 | 258 | // EchoService.EchoTwice 259 | args1.Msg = "abc" 260 | call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil) 261 | args2.Msg = "你好, 世界" 262 | call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil) 263 | args3.Msg = "Hello, 世界" 264 | call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil) 265 | 266 | call1 = <-call1.Done 267 | call2 = <-call2.Done 268 | call3 = <-call3.Done 269 | 270 | // call1 271 | if call1.Error != nil { 272 | t.Fatalf(`EchoService.EchoTwice: %v`, call1.Error) 273 | } 274 | if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg { 275 | t.Fatalf( 276 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 277 | args1.Msg+args1.Msg, 278 | call1.Reply.(*EchoResponse).Msg, 279 | ) 280 | } 281 | 282 | // call2 283 | if call2.Error != nil { 284 | t.Fatalf(`EchoService.EchoTwice: %v`, call2.Error) 285 | } 286 | if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg { 287 | t.Fatalf( 288 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 289 | args2.Msg+args2.Msg, 290 | call2.Reply.(*EchoResponse).Msg, 291 | ) 292 | } 293 | 294 | // call3 295 | if call3.Error != nil { 296 | t.Fatalf(`EchoService.EchoTwice: %v`, call3.Error) 297 | } 298 | if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg { 299 | t.Fatalf( 300 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 301 | args3.Msg+args3.Msg, 302 | call3.Reply.(*EchoResponse).Msg, 303 | ) 304 | } 305 | } 306 | 307 | func TestClientAsyncMassive(t *testing.T) { 308 | onceEcho.Do(setupEchoServer) 309 | 310 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 311 | client, err := DialEchoService("tcp", addr) 312 | if err != nil { 313 | t.Fatalf( 314 | `net.Dial("tcp", "%s:%d"): %v`, 315 | echoHost, echoPort, 316 | err, 317 | ) 318 | } 319 | defer client.Close() 320 | 321 | var args EchoRequest 322 | var reply EchoResponse 323 | 324 | // EchoService.EchoTwice 325 | args.Msg = echoMassiveRequest 326 | call := client.Go("EchoService.EchoTwice", &args, &reply, nil) 327 | 328 | call = <-call.Done 329 | if call.Error != nil { 330 | t.Fatalf(`EchoService.EchoTwice: %v`, call.Error) 331 | } 332 | if call.Reply.(*EchoResponse).Msg != echoMassiveResponse { 333 | got := call.Reply.(*EchoResponse).Msg 334 | if len(got) > 8 { 335 | got = got[:8] + "..." 336 | } 337 | t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 338 | len(call.Reply.(*EchoResponse).Msg), got, 339 | ) 340 | } 341 | } 342 | 343 | func TestClientAsyncMassiveBatches(t *testing.T) { 344 | onceEcho.Do(setupEchoServer) 345 | 346 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 347 | client, err := DialEchoService("tcp", addr) 348 | if err != nil { 349 | t.Fatalf( 350 | `net.Dial("tcp", "%s:%d"): %v`, 351 | echoHost, echoPort, 352 | err, 353 | ) 354 | } 355 | defer client.Close() 356 | 357 | var args1 EchoRequest 358 | var reply1 EchoResponse 359 | var args2 EchoRequest 360 | var reply2 EchoResponse 361 | var args3 EchoRequest 362 | var reply3 EchoResponse 363 | 364 | // EchoService.EchoTwice 365 | args1.Msg = echoMassiveRequest + "abc" 366 | call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil) 367 | args2.Msg = echoMassiveRequest + "你好, 世界" 368 | call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil) 369 | args3.Msg = echoMassiveRequest + "Hello, 世界" 370 | call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil) 371 | 372 | call1 = <-call1.Done 373 | call2 = <-call2.Done 374 | call3 = <-call3.Done 375 | 376 | // call1 377 | if call1.Error != nil { 378 | t.Fatalf(`EchoService.EchoTwice: %v`, call1.Error) 379 | } 380 | if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg { 381 | got := call1.Reply.(*EchoResponse).Msg 382 | if len(got) > 8 { 383 | got = got[:8] + "..." 384 | } 385 | t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 386 | len(call1.Reply.(*EchoResponse).Msg), got, 387 | ) 388 | } 389 | 390 | // call2 391 | if call2.Error != nil { 392 | t.Fatalf(`EchoService.EchoTwice: %v`, call2.Error) 393 | } 394 | if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg { 395 | got := call2.Reply.(*EchoResponse).Msg 396 | if len(got) > 8 { 397 | got = got[:8] + "..." 398 | } 399 | t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 400 | len(call2.Reply.(*EchoResponse).Msg), got, 401 | ) 402 | } 403 | 404 | // call3 405 | if call3.Error != nil { 406 | t.Fatalf(`EchoService.EchoTwice: %v`, call3.Error) 407 | } 408 | if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg { 409 | got := call3.Reply.(*EchoResponse).Msg 410 | if len(got) > 8 { 411 | got = got[:8] + "..." 412 | } 413 | t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 414 | len(call3.Reply.(*EchoResponse).Msg), got, 415 | ) 416 | } 417 | } 418 | 419 | func BenchmarkSyncEcho(b *testing.B) { 420 | onceEcho.Do(setupEchoServer) 421 | 422 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 423 | echoClient, err := DialEchoService("tcp", addr) 424 | if err != nil { 425 | b.Fatalf( 426 | `net.Dial("tcp", "%s:%d"): %v`, 427 | echoHost, echoPort, 428 | err, 429 | ) 430 | } 431 | defer echoClient.Close() 432 | 433 | b.ResetTimer() 434 | for i := 0; i < b.N; i++ { 435 | var args EchoRequest 436 | var reply *EchoResponse 437 | 438 | // EchoService.EchoTwice 439 | args.Msg = "abc" 440 | reply, err = echoClient.EchoTwice(&args) 441 | if err != nil { 442 | b.Fatalf(`EchoService.EchoTwice: %v`, err) 443 | } 444 | if reply.Msg != args.Msg+args.Msg { 445 | b.Fatalf( 446 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 447 | args.Msg+args.Msg, reply.Msg, 448 | ) 449 | } 450 | 451 | // EchoService.EchoTwice 452 | args.Msg = "你好, 世界" 453 | reply, err = echoClient.EchoTwice(&args) 454 | if err != nil { 455 | b.Fatalf(`EchoService.EchoTwice: %v`, err) 456 | } 457 | if reply.Msg != args.Msg+args.Msg { 458 | b.Fatalf( 459 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 460 | args.Msg+args.Msg, reply.Msg, 461 | ) 462 | } 463 | 464 | // EchoService.EchoTwice 465 | args.Msg = "Hello, 世界" 466 | reply, err = echoClient.EchoTwice(&args) 467 | if err != nil { 468 | b.Fatalf(`EchoService.EchoTwice: %v`, err) 469 | } 470 | if reply.Msg != args.Msg+args.Msg { 471 | b.Fatalf( 472 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 473 | args.Msg+args.Msg, reply.Msg, 474 | ) 475 | } 476 | } 477 | } 478 | 479 | func BenchmarkSyncMassive(b *testing.B) { 480 | onceEcho.Do(setupEchoServer) 481 | 482 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 483 | echoClient, err := DialEchoService("tcp", addr) 484 | if err != nil { 485 | b.Fatalf( 486 | `net.Dial("tcp", "%s:%d"): %v`, 487 | echoHost, echoPort, 488 | err, 489 | ) 490 | } 491 | defer echoClient.Close() 492 | 493 | b.ResetTimer() 494 | for i := 0; i < b.N; i++ { 495 | var args EchoRequest 496 | var reply *EchoResponse 497 | 498 | // EchoService.EchoTwice 499 | args.Msg = echoMassiveRequest + "abc" 500 | reply, err = echoClient.EchoTwice(&args) 501 | if err != nil { 502 | b.Fatalf(`EchoService.EchoTwice: %v`, err) 503 | } 504 | if reply.Msg != args.Msg+args.Msg { 505 | got := reply.Msg 506 | if len(got) > 8 { 507 | got = got[:8] + "..." 508 | } 509 | b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 510 | len(reply.Msg), got, 511 | ) 512 | } 513 | 514 | // EchoService.EchoTwice 515 | args.Msg = echoMassiveRequest + "你好, 世界" 516 | reply, err = echoClient.EchoTwice(&args) 517 | if err != nil { 518 | b.Fatalf(`EchoService.EchoTwice: %v`, err) 519 | } 520 | if reply.Msg != args.Msg+args.Msg { 521 | got := reply.Msg 522 | if len(got) > 8 { 523 | got = got[:8] + "..." 524 | } 525 | b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 526 | len(reply.Msg), got, 527 | ) 528 | } 529 | 530 | // EchoService.EchoTwice 531 | args.Msg = echoMassiveRequest + "Hello, 世界" 532 | reply, err = echoClient.EchoTwice(&args) 533 | if err != nil { 534 | b.Fatalf(`EchoService.EchoTwice: %v`, err) 535 | } 536 | if reply.Msg != args.Msg+args.Msg { 537 | got := reply.Msg 538 | if len(got) > 8 { 539 | got = got[:8] + "..." 540 | } 541 | b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 542 | len(reply.Msg), got, 543 | ) 544 | } 545 | } 546 | } 547 | 548 | func BenchmarkAsyncEcho(b *testing.B) { 549 | onceEcho.Do(setupEchoServer) 550 | 551 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 552 | client, err := DialEchoService("tcp", addr) 553 | if err != nil { 554 | b.Fatalf( 555 | `net.Dial("tcp", "%s:%d"): %v`, 556 | echoHost, echoPort, 557 | err, 558 | ) 559 | } 560 | defer client.Close() 561 | 562 | b.ResetTimer() 563 | for i := 0; i < b.N; i++ { 564 | var args1 EchoRequest 565 | var reply1 EchoResponse 566 | var args2 EchoRequest 567 | var reply2 EchoResponse 568 | var args3 EchoRequest 569 | var reply3 EchoResponse 570 | 571 | // EchoService.EchoTwice 572 | args1.Msg = "abc" 573 | call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil) 574 | args2.Msg = "你好, 世界" 575 | call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil) 576 | args3.Msg = "Hello, 世界" 577 | call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil) 578 | 579 | call1 = <-call1.Done 580 | call2 = <-call2.Done 581 | call3 = <-call3.Done 582 | 583 | // call1 584 | if call1.Error != nil { 585 | b.Fatalf(`EchoService.EchoTwice: %v`, call1.Error) 586 | } 587 | if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg { 588 | b.Fatalf( 589 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 590 | args1.Msg+args1.Msg, 591 | call1.Reply.(*EchoResponse).Msg, 592 | ) 593 | } 594 | 595 | // call2 596 | if call2.Error != nil { 597 | b.Fatalf(`EchoService.EchoTwice: %v`, call2.Error) 598 | } 599 | if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg { 600 | b.Fatalf( 601 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 602 | args2.Msg+args2.Msg, 603 | call2.Reply.(*EchoResponse).Msg, 604 | ) 605 | } 606 | 607 | // call3 608 | if call3.Error != nil { 609 | b.Fatalf(`EchoService.EchoTwice: %v`, call3.Error) 610 | } 611 | if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg { 612 | b.Fatalf( 613 | `EchoService.EchoTwice: expected = "%s", got = "%s"`, 614 | args3.Msg+args3.Msg, 615 | call3.Reply.(*EchoResponse).Msg, 616 | ) 617 | } 618 | } 619 | } 620 | 621 | func BenchmarkAsyncMassive(b *testing.B) { 622 | onceEcho.Do(setupEchoServer) 623 | 624 | addr := fmt.Sprintf("%s:%d", echoHost, echoPort) 625 | client, err := DialEchoService("tcp", addr) 626 | if err != nil { 627 | b.Fatalf( 628 | `net.Dial("tcp", "%s:%d"): %v`, 629 | echoHost, echoPort, 630 | err, 631 | ) 632 | } 633 | defer client.Close() 634 | 635 | b.ResetTimer() 636 | for i := 0; i < b.N; i++ { 637 | var args1 EchoRequest 638 | var reply1 EchoResponse 639 | var args2 EchoRequest 640 | var reply2 EchoResponse 641 | var args3 EchoRequest 642 | var reply3 EchoResponse 643 | 644 | // EchoService.EchoTwice 645 | args1.Msg = echoMassiveRequest + "abc" 646 | call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil) 647 | args2.Msg = echoMassiveRequest + "你好, 世界" 648 | call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil) 649 | args3.Msg = echoMassiveRequest + "Hello, 世界" 650 | call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil) 651 | 652 | call1 = <-call1.Done 653 | call2 = <-call2.Done 654 | call3 = <-call3.Done 655 | 656 | // call1 657 | if call1.Error != nil { 658 | b.Fatalf(`EchoService.EchoTwice: %v`, call1.Error) 659 | } 660 | if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg { 661 | got := call1.Reply.(*EchoResponse).Msg 662 | if len(got) > 8 { 663 | got = got[:8] + "..." 664 | } 665 | b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 666 | len(call1.Reply.(*EchoResponse).Msg), got, 667 | ) 668 | } 669 | 670 | // call2 671 | if call2.Error != nil { 672 | b.Fatalf(`EchoService.EchoTwice: %v`, call2.Error) 673 | } 674 | if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg { 675 | got := call2.Reply.(*EchoResponse).Msg 676 | if len(got) > 8 { 677 | got = got[:8] + "..." 678 | } 679 | b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 680 | len(call2.Reply.(*EchoResponse).Msg), got, 681 | ) 682 | } 683 | 684 | // call3 685 | if call3.Error != nil { 686 | b.Fatalf(`EchoService.EchoTwice: %v`, call3.Error) 687 | } 688 | if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg { 689 | got := call3.Reply.(*EchoResponse).Msg 690 | if len(got) > 8 { 691 | got = got[:8] + "..." 692 | } 693 | b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`, 694 | len(call3.Reply.(*EchoResponse).Msg), got, 695 | ) 696 | } 697 | } 698 | } 699 | -------------------------------------------------------------------------------- /examples/service.pb/proto.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate protoc --go_out=. arith.proto echo.proto 6 | //go:generate protoc --protorpc_out=. arith.proto echo.proto 7 | 8 | package service 9 | -------------------------------------------------------------------------------- /examples/stdrpc.pb/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2013 . All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | PROTO_FILES=$(sort $(wildcard ./*.proto)) 6 | 7 | default: $(PROTO_FILES) Makefile 8 | go install github.com/golang/protobuf/protoc-gen-go 9 | go install github.com/chai2010/protorpc/protoc-gen-stdrpc 10 | protoc --stdrpc_out=. ${PROTO_FILES} 11 | go test 12 | 13 | clean: 14 | -------------------------------------------------------------------------------- /examples/stdrpc.pb/arith.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: arith.proto 3 | 4 | /* 5 | Package service is a generated protocol buffer package. 6 | 7 | It is generated from these files: 8 | arith.proto 9 | echo.proto 10 | 11 | It has these top-level messages: 12 | ArithRequest 13 | ArithResponse 14 | EchoRequest 15 | EchoResponse 16 | */ 17 | package service 18 | 19 | import proto "github.com/golang/protobuf/proto" 20 | import fmt "fmt" 21 | import math "math" 22 | 23 | import "bufio" 24 | import "crypto/tls" 25 | import "errors" 26 | import "io" 27 | import "log" 28 | import "net" 29 | import "net/http" 30 | import "net/rpc" 31 | import "time" 32 | 33 | // Reference imports to suppress errors if they are not otherwise used. 34 | var _ = proto.Marshal 35 | var _ = fmt.Errorf 36 | var _ = math.Inf 37 | 38 | // This is a compile-time assertion to ensure that this generated file 39 | // is compatible with the proto package it is being compiled against. 40 | // A compilation error at this line likely means your copy of the 41 | // proto package needs to be updated. 42 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 43 | 44 | type ArithRequest struct { 45 | A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"` 46 | B int32 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"` 47 | } 48 | 49 | func (m *ArithRequest) Reset() { *m = ArithRequest{} } 50 | func (m *ArithRequest) String() string { return proto.CompactTextString(m) } 51 | func (*ArithRequest) ProtoMessage() {} 52 | func (*ArithRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 53 | 54 | func (m *ArithRequest) GetA() int32 { 55 | if m != nil { 56 | return m.A 57 | } 58 | return 0 59 | } 60 | 61 | func (m *ArithRequest) GetB() int32 { 62 | if m != nil { 63 | return m.B 64 | } 65 | return 0 66 | } 67 | 68 | type ArithResponse struct { 69 | C int32 `protobuf:"varint,1,opt,name=c" json:"c,omitempty"` 70 | } 71 | 72 | func (m *ArithResponse) Reset() { *m = ArithResponse{} } 73 | func (m *ArithResponse) String() string { return proto.CompactTextString(m) } 74 | func (*ArithResponse) ProtoMessage() {} 75 | func (*ArithResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } 76 | 77 | func (m *ArithResponse) GetC() int32 { 78 | if m != nil { 79 | return m.C 80 | } 81 | return 0 82 | } 83 | 84 | func init() { 85 | proto.RegisterType((*ArithRequest)(nil), "service.ArithRequest") 86 | proto.RegisterType((*ArithResponse)(nil), "service.ArithResponse") 87 | } 88 | 89 | type ArithService interface { 90 | Add(in *ArithRequest, out *ArithResponse) error 91 | Mul(in *ArithRequest, out *ArithResponse) error 92 | Div(in *ArithRequest, out *ArithResponse) error 93 | Error(in *ArithRequest, out *ArithResponse) error 94 | } 95 | 96 | // AcceptArithServiceClient accepts connections on the listener and serves requests 97 | // for each incoming connection. Accept blocks; the caller typically 98 | // invokes it in a go statement. 99 | func AcceptArithServiceClient(lis net.Listener, x ArithService) { 100 | srv := rpc.NewServer() 101 | if err := srv.RegisterName("service.ArithService", x); err != nil { 102 | log.Fatal(err) 103 | } 104 | 105 | for { 106 | conn, err := lis.Accept() 107 | if err != nil { 108 | log.Fatalf("lis.Accept(): %v\n", err) 109 | } 110 | go srv.ServeConn(conn) 111 | } 112 | } 113 | 114 | // RegisterArithService publish the given ArithService implementation on the server. 115 | func RegisterArithService(srv *rpc.Server, x ArithService) error { 116 | if err := srv.RegisterName("service.ArithService", x); err != nil { 117 | return err 118 | } 119 | return nil 120 | } 121 | 122 | // NewArithServiceServer returns a new ArithService Server. 123 | func NewArithServiceServer(x ArithService) *rpc.Server { 124 | srv := rpc.NewServer() 125 | if err := srv.RegisterName("service.ArithService", x); err != nil { 126 | log.Fatal(err) 127 | } 128 | return srv 129 | } 130 | 131 | // ListenAndServeArithService listen announces on the local network address laddr 132 | // and serves the given ArithService implementation. 133 | func ListenAndServeArithService(network, addr string, x ArithService) error { 134 | lis, err := net.Listen(network, addr) 135 | if err != nil { 136 | return err 137 | } 138 | defer lis.Close() 139 | 140 | srv := rpc.NewServer() 141 | if err := srv.RegisterName("service.ArithService", x); err != nil { 142 | return err 143 | } 144 | 145 | for { 146 | conn, err := lis.Accept() 147 | if err != nil { 148 | log.Fatalf("lis.Accept(): %v\n", err) 149 | } 150 | go srv.ServeConn(conn) 151 | } 152 | } 153 | 154 | // ServeArithService serves the given ArithService implementation. 155 | func ServeArithService(conn io.ReadWriteCloser, x ArithService) { 156 | srv := rpc.NewServer() 157 | if err := srv.RegisterName("service.ArithService", x); err != nil { 158 | log.Fatal(err) 159 | } 160 | srv.ServeConn(conn) 161 | } 162 | 163 | type ArithServiceClient struct { 164 | *rpc.Client 165 | } 166 | 167 | // NewArithServiceClient returns a ArithService stub to handle 168 | // requests to the set of ArithService at the other end of the connection. 169 | func NewArithServiceClient(conn io.ReadWriteCloser) *ArithServiceClient { 170 | c := rpc.NewClient(conn) 171 | return &ArithServiceClient{c} 172 | } 173 | 174 | func (c *ArithServiceClient) Add(in *ArithRequest) (out *ArithResponse, err error) { 175 | if in == nil { 176 | in = new(ArithRequest) 177 | } 178 | type Validator interface { 179 | Validate() error 180 | } 181 | if x, ok := proto.Message(in).(Validator); ok { 182 | if err := x.Validate(); err != nil { 183 | return nil, err 184 | } 185 | } 186 | out = new(ArithResponse) 187 | if err = c.Call("service.ArithService.Add", in, out); err != nil { 188 | return nil, err 189 | } 190 | if x, ok := proto.Message(out).(Validator); ok { 191 | if err := x.Validate(); err != nil { 192 | return out, err 193 | } 194 | } 195 | return out, nil 196 | } 197 | 198 | func (c *ArithServiceClient) AsyncAdd(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 199 | if in == nil { 200 | in = new(ArithRequest) 201 | } 202 | return c.Go( 203 | "service.ArithService.Add", 204 | in, out, 205 | done, 206 | ) 207 | } 208 | 209 | func (c *ArithServiceClient) Mul(in *ArithRequest) (out *ArithResponse, err error) { 210 | if in == nil { 211 | in = new(ArithRequest) 212 | } 213 | type Validator interface { 214 | Validate() error 215 | } 216 | if x, ok := proto.Message(in).(Validator); ok { 217 | if err := x.Validate(); err != nil { 218 | return nil, err 219 | } 220 | } 221 | out = new(ArithResponse) 222 | if err = c.Call("service.ArithService.Mul", in, out); err != nil { 223 | return nil, err 224 | } 225 | if x, ok := proto.Message(out).(Validator); ok { 226 | if err := x.Validate(); err != nil { 227 | return out, err 228 | } 229 | } 230 | return out, nil 231 | } 232 | 233 | func (c *ArithServiceClient) AsyncMul(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 234 | if in == nil { 235 | in = new(ArithRequest) 236 | } 237 | return c.Go( 238 | "service.ArithService.Mul", 239 | in, out, 240 | done, 241 | ) 242 | } 243 | 244 | func (c *ArithServiceClient) Div(in *ArithRequest) (out *ArithResponse, err error) { 245 | if in == nil { 246 | in = new(ArithRequest) 247 | } 248 | type Validator interface { 249 | Validate() error 250 | } 251 | if x, ok := proto.Message(in).(Validator); ok { 252 | if err := x.Validate(); err != nil { 253 | return nil, err 254 | } 255 | } 256 | out = new(ArithResponse) 257 | if err = c.Call("service.ArithService.Div", in, out); err != nil { 258 | return nil, err 259 | } 260 | if x, ok := proto.Message(out).(Validator); ok { 261 | if err := x.Validate(); err != nil { 262 | return out, err 263 | } 264 | } 265 | return out, nil 266 | } 267 | 268 | func (c *ArithServiceClient) AsyncDiv(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 269 | if in == nil { 270 | in = new(ArithRequest) 271 | } 272 | return c.Go( 273 | "service.ArithService.Div", 274 | in, out, 275 | done, 276 | ) 277 | } 278 | 279 | func (c *ArithServiceClient) Error(in *ArithRequest) (out *ArithResponse, err error) { 280 | if in == nil { 281 | in = new(ArithRequest) 282 | } 283 | type Validator interface { 284 | Validate() error 285 | } 286 | if x, ok := proto.Message(in).(Validator); ok { 287 | if err := x.Validate(); err != nil { 288 | return nil, err 289 | } 290 | } 291 | out = new(ArithResponse) 292 | if err = c.Call("service.ArithService.Error", in, out); err != nil { 293 | return nil, err 294 | } 295 | if x, ok := proto.Message(out).(Validator); ok { 296 | if err := x.Validate(); err != nil { 297 | return out, err 298 | } 299 | } 300 | return out, nil 301 | } 302 | 303 | func (c *ArithServiceClient) AsyncError(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call { 304 | if in == nil { 305 | in = new(ArithRequest) 306 | } 307 | return c.Go( 308 | "service.ArithService.Error", 309 | in, out, 310 | done, 311 | ) 312 | } 313 | 314 | // DialArithService connects to an ArithService at the specified network address. 315 | func DialArithService(network, addr string) (*ArithServiceClient, error) { 316 | c, err := rpc.Dial(network, addr) 317 | if err != nil { 318 | return nil, err 319 | } 320 | return &ArithServiceClient{c}, nil 321 | } 322 | 323 | // DialArithServiceTimeout connects to an ArithService at the specified network address. 324 | func DialArithServiceTimeout(network, addr string, timeout time.Duration) (*ArithServiceClient, error) { 325 | conn, err := net.DialTimeout(network, addr, timeout) 326 | if err != nil { 327 | return nil, err 328 | } 329 | return &ArithServiceClient{rpc.NewClient(conn)}, nil 330 | } 331 | 332 | // DialArithServiceHTTP connects to an HTTP RPC server at the specified network address 333 | // listening on the default HTTP RPC path. 334 | func DialArithServiceHTTP(network, address string) (*ArithServiceClient, error) { 335 | return DialArithServiceHTTPPath(network, address, rpc.DefaultRPCPath) 336 | } 337 | 338 | // DialArithServiceHTTPPath connects to an HTTP RPC server 339 | // at the specified network address and path. 340 | func DialArithServiceHTTPPath(network, address, path string) (*ArithServiceClient, error) { 341 | conn, err := net.Dial(network, address) 342 | if err != nil { 343 | return nil, err 344 | } 345 | return dialArithServicePath(network, address, path, conn) 346 | } 347 | 348 | // DialArithServiceHTTPS connects to an HTTPS RPC server at the specified network address 349 | // listening on the default HTTP RPC path. 350 | func DialArithServiceHTTPS(network, address string, tlsConfig *tls.Config) (*ArithServiceClient, error) { 351 | return DialArithServiceHTTPSPath(network, address, rpc.DefaultRPCPath, tlsConfig) 352 | } 353 | 354 | // DialArithServiceHTTPSPath connects to an HTTPS RPC server 355 | // at the specified network address and path. 356 | func DialArithServiceHTTPSPath(network, address, path string, tlsConfig *tls.Config) (*ArithServiceClient, error) { 357 | conn, err := tls.Dial(network, address, tlsConfig) 358 | if err != nil { 359 | return nil, err 360 | } 361 | return dialArithServicePath(network, address, path, conn) 362 | } 363 | 364 | func dialArithServicePath(network, address, path string, conn net.Conn) (*ArithServiceClient, error) { 365 | const net_rpc_connected = "200 Connected to Go RPC" 366 | 367 | io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n") 368 | 369 | // Require successful HTTP response 370 | // before switching to RPC protocol. 371 | resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"}) 372 | if err == nil && resp.Status == net_rpc_connected { 373 | return &ArithServiceClient{rpc.NewClient(conn)}, nil 374 | } 375 | if err == nil { 376 | err = errors.New("unexpected HTTP response: " + resp.Status) 377 | } 378 | conn.Close() 379 | return nil, &net.OpError{ 380 | Op: "dial-http", 381 | Net: network + " " + address, 382 | Addr: nil, 383 | Err: err, 384 | } 385 | } 386 | 387 | func init() { proto.RegisterFile("arith.proto", fileDescriptor0) } 388 | 389 | var fileDescriptor0 = []byte{ 390 | // 159 bytes of a gzipped FileDescriptorProto 391 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0x2c, 0xca, 0x2c, 392 | 0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 393 | 0x55, 0xd2, 0xe2, 0xe2, 0x71, 0x04, 0x89, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0xf1, 394 | 0x70, 0x31, 0x26, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x31, 0x26, 0x82, 0x78, 0x49, 0x12, 395 | 0x4c, 0x10, 0x5e, 0x92, 0x92, 0x2c, 0x17, 0x2f, 0x54, 0x6d, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0x2a, 396 | 0x48, 0x3a, 0x19, 0xa6, 0x38, 0xd9, 0xe8, 0x05, 0x23, 0xd4, 0xac, 0x60, 0x88, 0xd9, 0x42, 0x26, 397 | 0x5c, 0xcc, 0x89, 0x29, 0x29, 0x42, 0xa2, 0x7a, 0x50, 0xcb, 0xf4, 0x90, 0x6d, 0x92, 0x12, 0x43, 398 | 0x17, 0x86, 0x1a, 0x6a, 0xc2, 0xc5, 0x9c, 0x5b, 0x9a, 0x43, 0x86, 0xae, 0x94, 0xcc, 0x32, 0x52, 399 | 0x75, 0x99, 0x71, 0xb1, 0xa6, 0x16, 0x15, 0xe5, 0x17, 0x91, 0xa8, 0x2f, 0x89, 0x0d, 0x1c, 0x8a, 400 | 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x62, 0xfd, 0xbd, 0x54, 0x01, 0x00, 0x00, 401 | } 402 | -------------------------------------------------------------------------------- /examples/stdrpc.pb/arith.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package service; 8 | 9 | message ArithRequest { 10 | int32 a = 1; 11 | int32 b = 2; 12 | } 13 | 14 | message ArithResponse { 15 | int32 c = 1; 16 | } 17 | 18 | service ArithService { 19 | rpc add (ArithRequest) returns (ArithResponse); 20 | rpc mul (ArithRequest) returns (ArithResponse); 21 | rpc div (ArithRequest) returns (ArithResponse); 22 | rpc error (ArithRequest) returns (ArithResponse); 23 | } 24 | -------------------------------------------------------------------------------- /examples/stdrpc.pb/echo.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: echo.proto 3 | 4 | package service 5 | 6 | import proto "github.com/golang/protobuf/proto" 7 | import fmt "fmt" 8 | import math "math" 9 | 10 | import "bufio" 11 | import "crypto/tls" 12 | import "errors" 13 | import "io" 14 | import "log" 15 | import "net" 16 | import "net/http" 17 | import "net/rpc" 18 | import "time" 19 | 20 | // Reference imports to suppress errors if they are not otherwise used. 21 | var _ = proto.Marshal 22 | var _ = fmt.Errorf 23 | var _ = math.Inf 24 | 25 | type EchoRequest struct { 26 | Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"` 27 | } 28 | 29 | func (m *EchoRequest) Reset() { *m = EchoRequest{} } 30 | func (m *EchoRequest) String() string { return proto.CompactTextString(m) } 31 | func (*EchoRequest) ProtoMessage() {} 32 | func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } 33 | 34 | func (m *EchoRequest) GetMsg() string { 35 | if m != nil { 36 | return m.Msg 37 | } 38 | return "" 39 | } 40 | 41 | type EchoResponse struct { 42 | Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"` 43 | } 44 | 45 | func (m *EchoResponse) Reset() { *m = EchoResponse{} } 46 | func (m *EchoResponse) String() string { return proto.CompactTextString(m) } 47 | func (*EchoResponse) ProtoMessage() {} 48 | func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } 49 | 50 | func (m *EchoResponse) GetMsg() string { 51 | if m != nil { 52 | return m.Msg 53 | } 54 | return "" 55 | } 56 | 57 | func init() { 58 | proto.RegisterType((*EchoRequest)(nil), "service.EchoRequest") 59 | proto.RegisterType((*EchoResponse)(nil), "service.EchoResponse") 60 | } 61 | 62 | type EchoService interface { 63 | Echo(in *EchoRequest, out *EchoResponse) error 64 | EchoTwice(in *EchoRequest, out *EchoResponse) error 65 | } 66 | 67 | // AcceptEchoServiceClient accepts connections on the listener and serves requests 68 | // for each incoming connection. Accept blocks; the caller typically 69 | // invokes it in a go statement. 70 | func AcceptEchoServiceClient(lis net.Listener, x EchoService) { 71 | srv := rpc.NewServer() 72 | if err := srv.RegisterName("service.EchoService", x); err != nil { 73 | log.Fatal(err) 74 | } 75 | 76 | for { 77 | conn, err := lis.Accept() 78 | if err != nil { 79 | log.Fatalf("lis.Accept(): %v\n", err) 80 | } 81 | go srv.ServeConn(conn) 82 | } 83 | } 84 | 85 | // RegisterEchoService publish the given EchoService implementation on the server. 86 | func RegisterEchoService(srv *rpc.Server, x EchoService) error { 87 | if err := srv.RegisterName("service.EchoService", x); err != nil { 88 | return err 89 | } 90 | return nil 91 | } 92 | 93 | // NewEchoServiceServer returns a new EchoService Server. 94 | func NewEchoServiceServer(x EchoService) *rpc.Server { 95 | srv := rpc.NewServer() 96 | if err := srv.RegisterName("service.EchoService", x); err != nil { 97 | log.Fatal(err) 98 | } 99 | return srv 100 | } 101 | 102 | // ListenAndServeEchoService listen announces on the local network address laddr 103 | // and serves the given EchoService implementation. 104 | func ListenAndServeEchoService(network, addr string, x EchoService) error { 105 | lis, err := net.Listen(network, addr) 106 | if err != nil { 107 | return err 108 | } 109 | defer lis.Close() 110 | 111 | srv := rpc.NewServer() 112 | if err := srv.RegisterName("service.EchoService", x); err != nil { 113 | return err 114 | } 115 | 116 | for { 117 | conn, err := lis.Accept() 118 | if err != nil { 119 | log.Fatalf("lis.Accept(): %v\n", err) 120 | } 121 | go srv.ServeConn(conn) 122 | } 123 | } 124 | 125 | // ServeEchoService serves the given EchoService implementation. 126 | func ServeEchoService(conn io.ReadWriteCloser, x EchoService) { 127 | srv := rpc.NewServer() 128 | if err := srv.RegisterName("service.EchoService", x); err != nil { 129 | log.Fatal(err) 130 | } 131 | srv.ServeConn(conn) 132 | } 133 | 134 | type EchoServiceClient struct { 135 | *rpc.Client 136 | } 137 | 138 | // NewEchoServiceClient returns a EchoService stub to handle 139 | // requests to the set of EchoService at the other end of the connection. 140 | func NewEchoServiceClient(conn io.ReadWriteCloser) *EchoServiceClient { 141 | c := rpc.NewClient(conn) 142 | return &EchoServiceClient{c} 143 | } 144 | 145 | func (c *EchoServiceClient) Echo(in *EchoRequest) (out *EchoResponse, err error) { 146 | if in == nil { 147 | in = new(EchoRequest) 148 | } 149 | type Validator interface { 150 | Validate() error 151 | } 152 | if x, ok := proto.Message(in).(Validator); ok { 153 | if err := x.Validate(); err != nil { 154 | return nil, err 155 | } 156 | } 157 | out = new(EchoResponse) 158 | if err = c.Call("service.EchoService.Echo", in, out); err != nil { 159 | return nil, err 160 | } 161 | if x, ok := proto.Message(out).(Validator); ok { 162 | if err := x.Validate(); err != nil { 163 | return out, err 164 | } 165 | } 166 | return out, nil 167 | } 168 | 169 | func (c *EchoServiceClient) AsyncEcho(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call { 170 | if in == nil { 171 | in = new(EchoRequest) 172 | } 173 | return c.Go( 174 | "service.EchoService.Echo", 175 | in, out, 176 | done, 177 | ) 178 | } 179 | 180 | func (c *EchoServiceClient) EchoTwice(in *EchoRequest) (out *EchoResponse, err error) { 181 | if in == nil { 182 | in = new(EchoRequest) 183 | } 184 | type Validator interface { 185 | Validate() error 186 | } 187 | if x, ok := proto.Message(in).(Validator); ok { 188 | if err := x.Validate(); err != nil { 189 | return nil, err 190 | } 191 | } 192 | out = new(EchoResponse) 193 | if err = c.Call("service.EchoService.EchoTwice", in, out); err != nil { 194 | return nil, err 195 | } 196 | if x, ok := proto.Message(out).(Validator); ok { 197 | if err := x.Validate(); err != nil { 198 | return out, err 199 | } 200 | } 201 | return out, nil 202 | } 203 | 204 | func (c *EchoServiceClient) AsyncEchoTwice(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call { 205 | if in == nil { 206 | in = new(EchoRequest) 207 | } 208 | return c.Go( 209 | "service.EchoService.EchoTwice", 210 | in, out, 211 | done, 212 | ) 213 | } 214 | 215 | // DialEchoService connects to an EchoService at the specified network address. 216 | func DialEchoService(network, addr string) (*EchoServiceClient, error) { 217 | c, err := rpc.Dial(network, addr) 218 | if err != nil { 219 | return nil, err 220 | } 221 | return &EchoServiceClient{c}, nil 222 | } 223 | 224 | // DialEchoServiceTimeout connects to an EchoService at the specified network address. 225 | func DialEchoServiceTimeout(network, addr string, timeout time.Duration) (*EchoServiceClient, error) { 226 | conn, err := net.DialTimeout(network, addr, timeout) 227 | if err != nil { 228 | return nil, err 229 | } 230 | return &EchoServiceClient{rpc.NewClient(conn)}, nil 231 | } 232 | 233 | // DialEchoServiceHTTP connects to an HTTP RPC server at the specified network address 234 | // listening on the default HTTP RPC path. 235 | func DialEchoServiceHTTP(network, address string) (*EchoServiceClient, error) { 236 | return DialEchoServiceHTTPPath(network, address, rpc.DefaultRPCPath) 237 | } 238 | 239 | // DialEchoServiceHTTPPath connects to an HTTP RPC server 240 | // at the specified network address and path. 241 | func DialEchoServiceHTTPPath(network, address, path string) (*EchoServiceClient, error) { 242 | conn, err := net.Dial(network, address) 243 | if err != nil { 244 | return nil, err 245 | } 246 | return dialEchoServicePath(network, address, path, conn) 247 | } 248 | 249 | // DialEchoServiceHTTPS connects to an HTTPS RPC server at the specified network address 250 | // listening on the default HTTP RPC path. 251 | func DialEchoServiceHTTPS(network, address string, tlsConfig *tls.Config) (*EchoServiceClient, error) { 252 | return DialEchoServiceHTTPSPath(network, address, rpc.DefaultRPCPath, tlsConfig) 253 | } 254 | 255 | // DialEchoServiceHTTPSPath connects to an HTTPS RPC server 256 | // at the specified network address and path. 257 | func DialEchoServiceHTTPSPath(network, address, path string, tlsConfig *tls.Config) (*EchoServiceClient, error) { 258 | conn, err := tls.Dial(network, address, tlsConfig) 259 | if err != nil { 260 | return nil, err 261 | } 262 | return dialEchoServicePath(network, address, path, conn) 263 | } 264 | 265 | func dialEchoServicePath(network, address, path string, conn net.Conn) (*EchoServiceClient, error) { 266 | const net_rpc_connected = "200 Connected to Go RPC" 267 | 268 | io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n") 269 | 270 | // Require successful HTTP response 271 | // before switching to RPC protocol. 272 | resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"}) 273 | if err == nil && resp.Status == net_rpc_connected { 274 | return &EchoServiceClient{rpc.NewClient(conn)}, nil 275 | } 276 | if err == nil { 277 | err = errors.New("unexpected HTTP response: " + resp.Status) 278 | } 279 | conn.Close() 280 | return nil, &net.OpError{ 281 | Op: "dial-http", 282 | Net: network + " " + address, 283 | Addr: nil, 284 | Err: err, 285 | } 286 | } 287 | 288 | func init() { proto.RegisterFile("echo.proto", fileDescriptor1) } 289 | 290 | var fileDescriptor1 = []byte{ 291 | // 134 bytes of a gzipped FileDescriptorProto 292 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8, 293 | 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x55, 294 | 0x92, 0xe7, 0xe2, 0x76, 0x4d, 0xce, 0xc8, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12, 295 | 0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x95, 0x14, 296 | 0xb8, 0x78, 0x20, 0x0a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x31, 0x55, 0x18, 0xd5, 0x40, 0x8c, 297 | 0x08, 0x86, 0x98, 0x28, 0x64, 0xcc, 0xc5, 0x02, 0xe2, 0x0a, 0x89, 0xe8, 0x41, 0xed, 0xd0, 0x43, 298 | 0xb2, 0x40, 0x4a, 0x14, 0x4d, 0x14, 0x6a, 0xaa, 0x05, 0x17, 0x27, 0x88, 0x1f, 0x52, 0x0e, 0x32, 299 | 0x81, 0x14, 0x9d, 0x49, 0x6c, 0x60, 0x0f, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc1, 300 | 0xd4, 0xbd, 0xde, 0x00, 0x00, 0x00, 301 | } 302 | -------------------------------------------------------------------------------- /examples/stdrpc.pb/echo.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | package service; 8 | 9 | message EchoRequest { 10 | string msg = 1; 11 | } 12 | 13 | message EchoResponse { 14 | string msg = 1; 15 | } 16 | 17 | service EchoService { 18 | rpc Echo (EchoRequest) returns (EchoResponse); 19 | rpc EchoTwice (EchoRequest) returns (EchoResponse); 20 | } 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | // Copyright 2021 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | module github.com/chai2010/protorpc 6 | 7 | go 1.16 8 | 9 | require ( 10 | github.com/golang/protobuf v1.0.0 11 | github.com/golang/snappy v0.0.3 12 | ) 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.0.0 h1:lsek0oXi8iFE9L+EXARyHIjU5rlWIhhTkjDz3vHhWWQ= 2 | github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 3 | github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 4 | github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= 5 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 6 | -------------------------------------------------------------------------------- /hello.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ingore 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "log" 12 | 13 | "github.com/chai2010/protorpc" 14 | service "github.com/chai2010/protorpc/examples/service.pb" 15 | ) 16 | 17 | type Echo int 18 | 19 | func (t *Echo) Echo(args *service.EchoRequest, reply *service.EchoResponse) error { 20 | reply.Msg = args.Msg 21 | return nil 22 | } 23 | 24 | func (t *Echo) EchoTwice(args *service.EchoRequest, reply *service.EchoResponse) error { 25 | reply.Msg = args.Msg + args.Msg 26 | return nil 27 | } 28 | 29 | func init() { 30 | go service.ListenAndServeEchoService("tcp", `127.0.0.1:9527`, new(Echo)) 31 | } 32 | 33 | func main() { 34 | echoClient, err := service.DialEchoService("tcp", `127.0.0.1:9527`) 35 | if err != nil { 36 | log.Fatalf("service.DialEchoService: %v", err) 37 | } 38 | defer echoClient.Close() 39 | 40 | args := &service.EchoRequest{Msg: "你好, 世界!"} 41 | reply, err := echoClient.EchoTwice(args) 42 | if err != nil { 43 | log.Fatalf("echoClient.EchoTwice: %v", err) 44 | } 45 | fmt.Println(reply.Msg) 46 | 47 | // or use normal client 48 | client, err := protorpc.Dial("tcp", `127.0.0.1:9527`) 49 | if err != nil { 50 | log.Fatalf("protorpc.Dial: %v", err) 51 | } 52 | defer client.Close() 53 | 54 | echoClient1 := &service.EchoServiceClient{client} 55 | echoClient2 := &service.EchoServiceClient{client} 56 | reply, err = echoClient1.EchoTwice(args) 57 | reply, err = echoClient2.EchoTwice(args) 58 | _, _ = reply, err 59 | 60 | // Output: 61 | // 你好, 世界!你好, 世界! 62 | } 63 | -------------------------------------------------------------------------------- /hello2.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ingore 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "log" 12 | "net/rpc" 13 | "time" 14 | 15 | stdrpc "github.com/chai2010/protorpc/examples/stdrpc.pb" 16 | ) 17 | 18 | type Echo int 19 | 20 | func (t *Echo) Echo(args *stdrpc.EchoRequest, reply *stdrpc.EchoResponse) error { 21 | reply.Msg = args.Msg 22 | return nil 23 | } 24 | 25 | func (t *Echo) EchoTwice(args *stdrpc.EchoRequest, reply *stdrpc.EchoResponse) error { 26 | reply.Msg = args.Msg + args.Msg 27 | return nil 28 | } 29 | 30 | func init() { 31 | go stdrpc.ListenAndServeEchoService("tcp", `127.0.0.1:9527`, new(Echo)) 32 | } 33 | 34 | func main() { 35 | time.Sleep(time.Second) 36 | 37 | echoClient, err := stdrpc.DialEchoService("tcp", `127.0.0.1:9527`) 38 | if err != nil { 39 | log.Fatalf("stdrpc.DialEchoService: %v", err) 40 | } 41 | defer echoClient.Close() 42 | 43 | args := &stdrpc.EchoRequest{Msg: "你好, 世界!"} 44 | reply, err := echoClient.EchoTwice(args) 45 | if err != nil { 46 | log.Fatalf("echoClient.EchoTwice: %v", err) 47 | } 48 | fmt.Println(reply.Msg) 49 | 50 | // or use normal client 51 | client, err := rpc.Dial("tcp", `127.0.0.1:9527`) 52 | if err != nil { 53 | log.Fatalf("rpc.Dial: %v", err) 54 | } 55 | defer client.Close() 56 | 57 | echoClient1 := &stdrpc.EchoServiceClient{client} 58 | echoClient2 := &stdrpc.EchoServiceClient{client} 59 | reply, err = echoClient1.EchoTwice(args) 60 | reply, err = echoClient2.EchoTwice(args) 61 | _, _ = reply, err 62 | 63 | // Output: 64 | // 你好, 世界!你好, 世界! 65 | } 66 | -------------------------------------------------------------------------------- /protoc-gen-plugin/generator.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 . All rights reserved. 2 | // Use of this source code is governed by a Apache 3 | // license that can be found in the LICENSE file. 4 | 5 | package plugin 6 | 7 | import ( 8 | "github.com/golang/protobuf/protoc-gen-go/descriptor" 9 | "github.com/golang/protobuf/protoc-gen-go/generator" 10 | ) 11 | 12 | var pkgCodeGeneratorList []CodeGenerator 13 | 14 | type CodeGenerator interface { 15 | Name() string 16 | FileNameExt() string 17 | 18 | HeaderCode(g *generator.Generator, file *generator.FileDescriptor) string 19 | ServiceCode(g *generator.Generator, file *generator.FileDescriptor, svc *descriptor.ServiceDescriptorProto) string 20 | MessageCode(g *generator.Generator, file *generator.FileDescriptor, msg *descriptor.DescriptorProto) string 21 | } 22 | 23 | func RegisterCodeGenerator(g CodeGenerator) { 24 | pkgCodeGeneratorList = append(pkgCodeGeneratorList, g) 25 | } 26 | 27 | func getAllCodeGenerator() []CodeGenerator { 28 | return pkgCodeGeneratorList 29 | } 30 | 31 | func getAllServiceGeneratorNames() (names []string) { 32 | for _, g := range pkgCodeGeneratorList { 33 | names = append(names, g.Name()) 34 | } 35 | return 36 | } 37 | 38 | func getFirstServiceGeneratorName() string { 39 | if len(pkgCodeGeneratorList) > 0 { 40 | return pkgCodeGeneratorList[0].Name() 41 | } 42 | return "" 43 | } 44 | 45 | func getCodeGenerator(name string) CodeGenerator { 46 | for _, g := range pkgCodeGeneratorList { 47 | if g.Name() == name { 48 | return g 49 | } 50 | } 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /protoc-gen-plugin/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 . All rights reserved. 2 | // Use of this source code is governed by a Apache 3 | // license that can be found in the LICENSE file. 4 | 5 | package plugin 6 | 7 | import ( 8 | "io/ioutil" 9 | "log" 10 | "os" 11 | "strings" 12 | 13 | "github.com/golang/protobuf/proto" 14 | "github.com/golang/protobuf/protoc-gen-go/generator" 15 | ) 16 | 17 | func Main() { 18 | mainPlugin := new(mainPlugin) 19 | generator.RegisterPlugin(mainPlugin) 20 | 21 | // Begin by allocating a generator. The request and response structures are stored there 22 | // so we can do error handling easily - the response structure contains the field to 23 | // report failure. 24 | g := generator.New() 25 | if len(getAllCodeGenerator()) == 0 { 26 | g.Fail("no code generator plugin") 27 | } 28 | 29 | pkgReadRequetFromStdin(g) 30 | pkgGenerateAllFiles(g, mainPlugin) 31 | pkgWriteResponseToStdout(g) 32 | } 33 | 34 | func pkgGenerateAllFiles(g *generator.Generator, plugin *mainPlugin) { 35 | // set default plugins 36 | // protoc --xxx_out=. x.proto 37 | plugin.InitService(pkgGetUserPlugin(g)) 38 | 39 | // parse command line parameters 40 | g.CommandLineParameters("plugins=" + plugin.Name()) 41 | 42 | // Create a wrapped version of the Descriptors and EnumDescriptors that 43 | // point to the file that defines them. 44 | g.WrapTypes() 45 | 46 | g.SetPackageNames() 47 | g.BuildTypeNameMap() 48 | 49 | g.GenerateAllFiles() 50 | 51 | // skip non *.pb.xxx.go 52 | respFileList := g.Response.File[:0] 53 | for _, file := range g.Response.File { 54 | fileName := file.GetName() 55 | extName := plugin.FileNameExt() 56 | 57 | if strings.HasSuffix(fileName, extName) { 58 | respFileList = append(respFileList, file) 59 | } 60 | } 61 | g.Response.File = respFileList 62 | } 63 | 64 | func pkgReadRequetFromStdin(g *generator.Generator) { 65 | data, err := ioutil.ReadAll(os.Stdin) 66 | if err != nil { 67 | g.Error(err, "reading input") 68 | } 69 | 70 | if err := proto.Unmarshal(data, g.Request); err != nil { 71 | g.Error(err, "parsing input proto") 72 | } 73 | 74 | if len(g.Request.FileToGenerate) == 0 { 75 | g.Fail("no files to generate") 76 | } 77 | } 78 | 79 | func pkgWriteResponseToStdout(g *generator.Generator) { 80 | data, err := proto.Marshal(g.Response) 81 | if err != nil { 82 | g.Error(err, "failed to marshal output proto") 83 | } 84 | _, err = os.Stdout.Write(data) 85 | if err != nil { 86 | g.Error(err, "failed to write output proto") 87 | } 88 | } 89 | 90 | func pkgGetUserPlugin(g *generator.Generator) CodeGenerator { 91 | args := g.Request.GetParameter() 92 | userPluginName := pkgGetParameterValue(args, "plugin") 93 | if userPluginName == "" { 94 | userPluginName = getFirstServiceGeneratorName() 95 | } 96 | 97 | userPlugin := getCodeGenerator(userPluginName) 98 | if userPlugin == nil { 99 | log.Print("protoc-gen-plugin: registor plugins:", getAllServiceGeneratorNames()) 100 | g.Fail("invalid plugin option:", userPluginName) 101 | } 102 | 103 | return userPlugin 104 | } 105 | 106 | func pkgGetParameterValue(parameter, key string) string { 107 | for _, p := range strings.Split(parameter, ",") { 108 | if i := strings.Index(p, "="); i > 0 { 109 | if p[0:i] == key { 110 | return p[i+1:] 111 | } 112 | } 113 | } 114 | return "" 115 | } 116 | -------------------------------------------------------------------------------- /protoc-gen-plugin/main_plugin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 . All rights reserved. 2 | // Use of this source code is governed by a Apache 3 | // license that can be found in the LICENSE file. 4 | 5 | package plugin 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "go/format" 11 | "path" 12 | "strings" 13 | 14 | "github.com/golang/protobuf/proto" 15 | "github.com/golang/protobuf/protoc-gen-go/generator" 16 | plugin "github.com/golang/protobuf/protoc-gen-go/plugin" 17 | ) 18 | 19 | // mainPlugin produce the Service interface. 20 | type mainPlugin struct { 21 | *generator.Generator 22 | CodeGenerator 23 | } 24 | 25 | // Name returns the name of the plugin. 26 | func (p *mainPlugin) Name() string { return "main-plugin" } 27 | 28 | // Init is called once after data structures are built but before 29 | // code generation begins. 30 | func (p *mainPlugin) Init(g *generator.Generator) { 31 | p.Generator = g 32 | } 33 | 34 | func (p *mainPlugin) InitService(g CodeGenerator) { 35 | p.CodeGenerator = g 36 | } 37 | 38 | // Generate produces the code generated by the plugin for this file. 39 | func (p *mainPlugin) GenerateImports(file *generator.FileDescriptor) { 40 | // skip 41 | } 42 | 43 | // Generate generates the Service interface. 44 | // rpc service can't handle other proto message!!! 45 | func (p *mainPlugin) Generate(file *generator.FileDescriptor) { 46 | if !p.isFileNeedGenerate(file) { 47 | return 48 | } 49 | 50 | var buf bytes.Buffer 51 | fmt.Fprintln(&buf, p.HeaderCode(p.Generator, file)) 52 | 53 | for _, msg := range file.MessageType { 54 | fmt.Fprintln(&buf, p.MessageCode(p.Generator, file, msg)) 55 | } 56 | 57 | for _, svc := range file.Service { 58 | fmt.Fprintln(&buf, p.ServiceCode(p.Generator, file, svc)) 59 | } 60 | 61 | fileContent := buf.String() 62 | if code, err := format.Source(buf.Bytes()); err == nil { 63 | fileContent = string(code) 64 | } 65 | 66 | p.Generator.Response.File = append(p.Generator.Response.File, &plugin.CodeGeneratorResponse_File{ 67 | Name: proto.String(p.goFileName(file)), 68 | Content: proto.String(fileContent), 69 | }) 70 | } 71 | 72 | func (p *mainPlugin) isFileNeedGenerate(file *generator.FileDescriptor) bool { 73 | for _, v := range p.Generator.Request.FileToGenerate { 74 | if v == file.GetName() { 75 | return true 76 | } 77 | } 78 | return false 79 | } 80 | 81 | func (p *mainPlugin) goFileName(file *generator.FileDescriptor) string { 82 | name := *file.Name 83 | if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" { 84 | name = name[:len(name)-len(ext)] 85 | } 86 | name += p.FileNameExt() 87 | 88 | // Does the file have a "go_package" option? 89 | // If it does, it may override the filename. 90 | if impPath, _, ok := p.goPackageOption(file); ok && impPath != "" { 91 | // Replace the existing dirname with the declared import path. 92 | _, name = path.Split(name) 93 | name = path.Join(impPath, name) 94 | return name 95 | } 96 | 97 | return name 98 | } 99 | 100 | func (p *mainPlugin) goPackageOption(file *generator.FileDescriptor) (impPath, pkg string, ok bool) { 101 | pkg = file.GetOptions().GetGoPackage() 102 | if pkg == "" { 103 | return 104 | } 105 | ok = true 106 | // The presence of a slash implies there's an import path. 107 | slash := strings.LastIndex(pkg, "/") 108 | if slash < 0 { 109 | return 110 | } 111 | impPath, pkg = pkg, pkg[slash+1:] 112 | // A semicolon-delimited suffix overrides the package name. 113 | sc := strings.IndexByte(impPath, ';') 114 | if sc < 0 { 115 | return 116 | } 117 | impPath, pkg = impPath[:sc], impPath[sc+1:] 118 | return 119 | } 120 | -------------------------------------------------------------------------------- /protoc-gen-protorpc/env.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | const ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX = "ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX" 8 | -------------------------------------------------------------------------------- /protoc-gen-protorpc/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "bytes" 9 | "log" 10 | "os" 11 | "text/template" 12 | 13 | plugin "github.com/chai2010/protorpc/protoc-gen-plugin" 14 | "github.com/golang/protobuf/protoc-gen-go/descriptor" 15 | "github.com/golang/protobuf/protoc-gen-go/generator" 16 | ) 17 | 18 | var flagPrefix = os.Getenv(ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX) 19 | 20 | func main() { 21 | plugin.Main() 22 | } 23 | 24 | func init() { 25 | plugin.RegisterCodeGenerator(new(protorpcPlugin)) 26 | } 27 | 28 | type protorpcPlugin struct{} 29 | 30 | func (p *protorpcPlugin) Name() string { return "protorpc-go" } 31 | func (p *protorpcPlugin) FileNameExt() string { return ".pb.protorpc.go" } 32 | 33 | func (p *protorpcPlugin) HeaderCode(g *generator.Generator, file *generator.FileDescriptor) string { 34 | const tmpl = ` 35 | {{- $G := .G -}} 36 | {{- $File := .File -}} 37 | 38 | // Code generated by protoc-gen-protorpc. DO NOT EDIT. 39 | // 40 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin 41 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc 42 | // 43 | // source: {{$File.GetName}} 44 | 45 | package {{$File.PackageName}} 46 | 47 | import ( 48 | "fmt" 49 | "io" 50 | "log" 51 | "net" 52 | "net/rpc" 53 | "time" 54 | 55 | "github.com/chai2010/protorpc" 56 | "github.com/golang/protobuf/proto" 57 | ) 58 | 59 | var ( 60 | _ = fmt.Sprint 61 | _ = io.Reader(nil) 62 | _ = log.Print 63 | _ = net.Addr(nil) 64 | _ = rpc.Call{} 65 | _ = time.Second 66 | 67 | _ = proto.String 68 | _ = protorpc.Dial 69 | ) 70 | ` 71 | var buf bytes.Buffer 72 | t := template.Must(template.New("").Parse(tmpl)) 73 | err := t.Execute(&buf, 74 | struct { 75 | G *generator.Generator 76 | File *generator.FileDescriptor 77 | Prefix string 78 | }{ 79 | G: g, 80 | File: file, 81 | Prefix: flagPrefix, 82 | }, 83 | ) 84 | if err != nil { 85 | log.Fatal(err) 86 | } 87 | 88 | return buf.String() 89 | } 90 | 91 | func (p *protorpcPlugin) ServiceCode(g *generator.Generator, file *generator.FileDescriptor, svc *descriptor.ServiceDescriptorProto) string { 92 | var code string 93 | code += p.genServiceInterface(g, file, svc) 94 | code += p.genServiceServer(g, file, svc) 95 | code += p.genServiceClient(g, file, svc) 96 | return code 97 | } 98 | 99 | func (p *protorpcPlugin) MessageCode(g *generator.Generator, file *generator.FileDescriptor, msg *descriptor.DescriptorProto) string { 100 | return "" 101 | } 102 | 103 | func (p *protorpcPlugin) genServiceInterface( 104 | g *generator.Generator, 105 | file *generator.FileDescriptor, 106 | svc *descriptor.ServiceDescriptorProto, 107 | ) string { 108 | const serviceInterfaceTmpl = ` 109 | type {{.Prefix}}{{.ServiceName}} interface { 110 | {{.CallMethodList}} 111 | } 112 | ` 113 | const callMethodTmpl = ` 114 | {{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}) error` 115 | 116 | // gen call method list 117 | var callMethodList string 118 | for _, m := range svc.Method { 119 | out := bytes.NewBuffer([]byte{}) 120 | t := template.Must(template.New("").Parse(callMethodTmpl)) 121 | t.Execute(out, &struct { 122 | Prefix string 123 | ServiceName string 124 | MethodName string 125 | ArgsType string 126 | ReplyType string 127 | }{ 128 | Prefix: flagPrefix, 129 | ServiceName: generator.CamelCase(svc.GetName()), 130 | MethodName: generator.CamelCase(m.GetName()), 131 | ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())), 132 | ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())), 133 | }) 134 | callMethodList += out.String() 135 | 136 | g.RecordTypeUse(m.GetInputType()) 137 | g.RecordTypeUse(m.GetOutputType()) 138 | } 139 | 140 | // gen all interface code 141 | { 142 | out := bytes.NewBuffer([]byte{}) 143 | t := template.Must(template.New("").Parse(serviceInterfaceTmpl)) 144 | t.Execute(out, &struct { 145 | Prefix string 146 | ServiceName string 147 | CallMethodList string 148 | }{ 149 | Prefix: flagPrefix, 150 | ServiceName: generator.CamelCase(svc.GetName()), 151 | CallMethodList: callMethodList, 152 | }) 153 | 154 | return out.String() 155 | } 156 | } 157 | 158 | func (p *protorpcPlugin) genServiceServer( 159 | g *generator.Generator, 160 | file *generator.FileDescriptor, 161 | svc *descriptor.ServiceDescriptorProto, 162 | ) string { 163 | const serviceHelperFunTmpl = ` 164 | // {{.Prefix}}Accept{{.ServiceName}}Client accepts connections on the listener and serves requests 165 | // for each incoming connection. Accept blocks; the caller typically 166 | // invokes it in a go statement. 167 | func {{.Prefix}}Accept{{.ServiceName}}Client(lis net.Listener, x {{.Prefix}}{{.ServiceName}}) { 168 | srv := rpc.NewServer() 169 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 170 | log.Fatal(err) 171 | } 172 | 173 | for { 174 | conn, err := lis.Accept() 175 | if err != nil { 176 | log.Fatalf("lis.Accept(): %v\n", err) 177 | } 178 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 179 | } 180 | } 181 | 182 | // {{.Prefix}}Register{{.ServiceName}} publish the given {{.Prefix}}{{.ServiceName}} implementation on the server. 183 | func {{.Prefix}}Register{{.ServiceName}}(srv *rpc.Server, x {{.Prefix}}{{.ServiceName}}) error { 184 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 185 | return err 186 | } 187 | return nil 188 | } 189 | 190 | // {{.Prefix}}New{{.ServiceName}}Server returns a new {{.Prefix}}{{.ServiceName}} Server. 191 | func {{.Prefix}}New{{.ServiceName}}Server(x {{.Prefix}}{{.ServiceName}}) *rpc.Server { 192 | srv := rpc.NewServer() 193 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 194 | log.Fatal(err) 195 | } 196 | return srv 197 | } 198 | 199 | // {{.Prefix}}ListenAndServe{{.ServiceName}} listen announces on the local network address laddr 200 | // and serves the given {{.ServiceName}} implementation. 201 | func {{.Prefix}}ListenAndServe{{.ServiceName}}(network, addr string, x {{.Prefix}}{{.ServiceName}}) error { 202 | lis, err := net.Listen(network, addr) 203 | if err != nil { 204 | return err 205 | } 206 | defer lis.Close() 207 | 208 | srv := rpc.NewServer() 209 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 210 | return err 211 | } 212 | 213 | for { 214 | conn, err := lis.Accept() 215 | if err != nil { 216 | log.Fatalf("lis.Accept(): %v\n", err) 217 | } 218 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 219 | } 220 | } 221 | 222 | // {{.Prefix}}Serve{{.ServiceName}} serves the given {{.Prefix}}{{.ServiceName}} implementation. 223 | func {{.Prefix}}Serve{{.ServiceName}}(conn io.ReadWriteCloser, x {{.Prefix}}{{.ServiceName}}) { 224 | srv := rpc.NewServer() 225 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 226 | log.Fatal(err) 227 | } 228 | srv.ServeCodec(protorpc.NewServerCodec(conn)) 229 | } 230 | ` 231 | { 232 | out := bytes.NewBuffer([]byte{}) 233 | t := template.Must(template.New("").Parse(serviceHelperFunTmpl)) 234 | t.Execute(out, &struct { 235 | Prefix string 236 | PackageName string 237 | ServiceName string 238 | ServiceRegisterName string 239 | }{ 240 | Prefix: flagPrefix, 241 | PackageName: file.GetPackage(), 242 | ServiceName: generator.CamelCase(svc.GetName()), 243 | ServiceRegisterName: p.makeServiceRegisterName( 244 | file, file.GetPackage(), generator.CamelCase(svc.GetName()), 245 | ), 246 | }) 247 | 248 | return out.String() 249 | } 250 | } 251 | 252 | func (p *protorpcPlugin) genServiceClient( 253 | g *generator.Generator, 254 | file *generator.FileDescriptor, 255 | svc *descriptor.ServiceDescriptorProto, 256 | ) string { 257 | const clientHelperFuncTmpl = ` 258 | type {{.Prefix}}{{.ServiceName}}Client struct { 259 | *rpc.Client 260 | } 261 | 262 | // {{.Prefix}}New{{.ServiceName}}Client returns a {{.Prefix}}{{.ServiceName}} stub to handle 263 | // requests to the set of {{.Prefix}}{{.ServiceName}} at the other end of the connection. 264 | func {{.Prefix}}New{{.ServiceName}}Client(conn io.ReadWriteCloser) (*{{.Prefix}}{{.ServiceName}}Client) { 265 | c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn)) 266 | return &{{.Prefix}}{{.ServiceName}}Client{c} 267 | } 268 | 269 | {{.MethodList}} 270 | 271 | // {{.Prefix}}Dial{{.ServiceName}} connects to an {{.Prefix}}{{.ServiceName}} at the specified network address. 272 | func {{.Prefix}}Dial{{.ServiceName}}(network, addr string) (*{{.Prefix}}{{.ServiceName}}Client, error) { 273 | c, err := protorpc.Dial(network, addr) 274 | if err != nil { 275 | return nil, err 276 | } 277 | return &{{.Prefix}}{{.ServiceName}}Client{c}, nil 278 | } 279 | 280 | // {{.Prefix}}Dial{{.ServiceName}}Timeout connects to an {{.Prefix}}{{.ServiceName}} at the specified network address. 281 | func {{.Prefix}}Dial{{.ServiceName}}Timeout(network, addr string, timeout time.Duration) (*{{.Prefix}}{{.ServiceName}}Client, error) { 282 | c, err := protorpc.DialTimeout(network, addr, timeout) 283 | if err != nil { 284 | return nil, err 285 | } 286 | return &{{.Prefix}}{{.ServiceName}}Client{c}, nil 287 | } 288 | ` 289 | const clientMethodTmpl = ` 290 | func (c *{{.Prefix}}{{.ServiceName}}Client) {{.MethodName}}(in *{{.ArgsType}}) (out *{{.ReplyType}}, err error) { 291 | if in == nil { 292 | in = new({{.ArgsType}}) 293 | } 294 | 295 | type Validator interface { 296 | Validate() error 297 | } 298 | if x, ok := proto.Message(in).(Validator); ok { 299 | if err := x.Validate(); err != nil { 300 | return nil, err 301 | } 302 | } 303 | 304 | out = new({{.ReplyType}}) 305 | if err = c.Call("{{.ServiceRegisterName}}.{{.MethodName}}", in, out); err != nil { 306 | return nil, err 307 | } 308 | 309 | if x, ok := proto.Message(out).(Validator); ok { 310 | if err := x.Validate(); err != nil { 311 | return out, err 312 | } 313 | } 314 | 315 | return out, nil 316 | } 317 | 318 | func (c *{{.Prefix}}{{.ServiceName}}Client) Async{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}, done chan *rpc.Call) *rpc.Call { 319 | if in == nil { 320 | in = new({{.ArgsType}}) 321 | } 322 | return c.Go( 323 | "{{.ServiceRegisterName}}.{{.MethodName}}", 324 | in, out, 325 | done, 326 | ) 327 | } 328 | ` 329 | 330 | // gen client method list 331 | var methodList string 332 | for _, m := range svc.Method { 333 | out := bytes.NewBuffer([]byte{}) 334 | t := template.Must(template.New("").Parse(clientMethodTmpl)) 335 | t.Execute(out, &struct { 336 | Prefix string 337 | ServiceName string 338 | ServiceRegisterName string 339 | MethodName string 340 | ArgsType string 341 | ReplyType string 342 | }{ 343 | Prefix: flagPrefix, 344 | ServiceName: generator.CamelCase(svc.GetName()), 345 | ServiceRegisterName: p.makeServiceRegisterName( 346 | file, file.GetPackage(), generator.CamelCase(svc.GetName()), 347 | ), 348 | MethodName: generator.CamelCase(m.GetName()), 349 | ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())), 350 | ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())), 351 | }) 352 | methodList += out.String() 353 | } 354 | 355 | // gen all client code 356 | { 357 | out := bytes.NewBuffer([]byte{}) 358 | t := template.Must(template.New("").Parse(clientHelperFuncTmpl)) 359 | t.Execute(out, &struct { 360 | Prefix string 361 | PackageName string 362 | ServiceName string 363 | MethodList string 364 | }{ 365 | Prefix: flagPrefix, 366 | PackageName: file.GetPackage(), 367 | ServiceName: generator.CamelCase(svc.GetName()), 368 | MethodList: methodList, 369 | }) 370 | 371 | return out.String() 372 | } 373 | } 374 | 375 | func (p *protorpcPlugin) makeServiceRegisterName( 376 | file *generator.FileDescriptor, 377 | packageName, serviceName string, 378 | ) string { 379 | // return packageName + "." + serviceName 380 | return serviceName 381 | } 382 | -------------------------------------------------------------------------------- /protoc-gen-stdrpc/_main-ignore.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "bytes" 9 | "log" 10 | "text/template" 11 | 12 | plugin "github.com/chai2010/protorpc/protoc-gen-plugin" 13 | "github.com/golang/protobuf/protoc-gen-go/descriptor" 14 | "github.com/golang/protobuf/protoc-gen-go/generator" 15 | ) 16 | 17 | func main() { 18 | plugin.Main() 19 | } 20 | 21 | func init() { 22 | plugin.RegisterCodeGenerator(new(protorpcPlugin)) 23 | } 24 | 25 | type protorpcPlugin struct{} 26 | 27 | func (p *protorpcPlugin) Name() string { return "stdrpc-go" } 28 | func (p *protorpcPlugin) FileNameExt() string { return ".pb.stdrpc.go" } 29 | 30 | func (p *protorpcPlugin) HeaderCode(g *generator.Generator, file *generator.FileDescriptor) string { 31 | const tmpl = ` 32 | {{- $G := .G -}} 33 | {{- $File := .File -}} 34 | 35 | // Code generated by protoc-gen-stdrpc. DO NOT EDIT. 36 | // 37 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin 38 | // plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-stdrpc 39 | // 40 | // source: {{$File.GetName}} 41 | 42 | package {{$File.PackageName}} 43 | 44 | import ( 45 | "fmt" 46 | "io" 47 | "log" 48 | "net" 49 | "net/rpc" 50 | "time" 51 | 52 | "github.com/golang/protobuf/proto" 53 | ) 54 | 55 | var ( 56 | _ = fmt.Sprint 57 | _ = io.Reader(nil) 58 | _ = log.Print 59 | _ = net.Addr(nil) 60 | _ = rpc.Call{} 61 | _ = time.Second 62 | 63 | _ = proto.String 64 | ) 65 | ` 66 | var buf bytes.Buffer 67 | t := template.Must(template.New("").Parse(tmpl)) 68 | err := t.Execute(&buf, 69 | struct { 70 | G *generator.Generator 71 | File *generator.FileDescriptor 72 | }{ 73 | G: g, 74 | File: file, 75 | }, 76 | ) 77 | if err != nil { 78 | log.Fatal(err) 79 | } 80 | 81 | return buf.String() 82 | } 83 | 84 | func (p *protorpcPlugin) ServiceCode(g *generator.Generator, file *generator.FileDescriptor, svc *descriptor.ServiceDescriptorProto) string { 85 | var code string 86 | code += p.genServiceInterface(g, file, svc) 87 | code += p.genServiceServer(g, file, svc) 88 | code += p.genServiceClient(g, file, svc) 89 | return code 90 | } 91 | 92 | func (p *protorpcPlugin) MessageCode(g *generator.Generator, file *generator.FileDescriptor, msg *descriptor.DescriptorProto) string { 93 | return "" 94 | } 95 | 96 | func (p *protorpcPlugin) genServiceInterface( 97 | g *generator.Generator, 98 | file *generator.FileDescriptor, 99 | svc *descriptor.ServiceDescriptorProto, 100 | ) string { 101 | const serviceInterfaceTmpl = ` 102 | type {{.ServiceName}} interface { 103 | {{.CallMethodList}} 104 | } 105 | ` 106 | const callMethodTmpl = ` 107 | {{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}) error` 108 | 109 | // gen call method list 110 | var callMethodList string 111 | for _, m := range svc.Method { 112 | out := bytes.NewBuffer([]byte{}) 113 | t := template.Must(template.New("").Parse(callMethodTmpl)) 114 | t.Execute(out, &struct{ ServiceName, MethodName, ArgsType, ReplyType string }{ 115 | ServiceName: generator.CamelCase(svc.GetName()), 116 | MethodName: generator.CamelCase(m.GetName()), 117 | ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())), 118 | ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())), 119 | }) 120 | callMethodList += out.String() 121 | 122 | g.RecordTypeUse(m.GetInputType()) 123 | g.RecordTypeUse(m.GetOutputType()) 124 | } 125 | 126 | // gen all interface code 127 | { 128 | out := bytes.NewBuffer([]byte{}) 129 | t := template.Must(template.New("").Parse(serviceInterfaceTmpl)) 130 | t.Execute(out, &struct{ ServiceName, CallMethodList string }{ 131 | ServiceName: generator.CamelCase(svc.GetName()), 132 | CallMethodList: callMethodList, 133 | }) 134 | 135 | return out.String() 136 | } 137 | } 138 | 139 | func (p *protorpcPlugin) genServiceServer( 140 | g *generator.Generator, 141 | file *generator.FileDescriptor, 142 | svc *descriptor.ServiceDescriptorProto, 143 | ) string { 144 | const serviceHelperFunTmpl = ` 145 | // Accept{{.ServiceName}}Client accepts connections on the listener and serves requests 146 | // for each incoming connection. Accept blocks; the caller typically 147 | // invokes it in a go statement. 148 | func Accept{{.ServiceName}}Client(lis net.Listener, x {{.ServiceName}}) { 149 | srv := rpc.NewServer() 150 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 151 | log.Fatal(err) 152 | } 153 | 154 | for { 155 | conn, err := lis.Accept() 156 | if err != nil { 157 | log.Fatalf("lis.Accept(): %v\n", err) 158 | } 159 | go srv.ServeConn(conn) 160 | } 161 | } 162 | 163 | // Register{{.ServiceName}} publish the given {{.ServiceName}} implementation on the server. 164 | func Register{{.ServiceName}}(srv *rpc.Server, x {{.ServiceName}}) error { 165 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 166 | return err 167 | } 168 | return nil 169 | } 170 | 171 | // New{{.ServiceName}}Server returns a new {{.ServiceName}} Server. 172 | func New{{.ServiceName}}Server(x {{.ServiceName}}) *rpc.Server { 173 | srv := rpc.NewServer() 174 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 175 | log.Fatal(err) 176 | } 177 | return srv 178 | } 179 | 180 | // ListenAndServe{{.ServiceName}} listen announces on the local network address laddr 181 | // and serves the given {{.ServiceName}} implementation. 182 | func ListenAndServe{{.ServiceName}}(network, addr string, x {{.ServiceName}}) error { 183 | lis, err := net.Listen(network, addr) 184 | if err != nil { 185 | return err 186 | } 187 | defer lis.Close() 188 | 189 | srv := rpc.NewServer() 190 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 191 | return err 192 | } 193 | 194 | for { 195 | conn, err := lis.Accept() 196 | if err != nil { 197 | log.Fatalf("lis.Accept(): %v\n", err) 198 | } 199 | go srv.ServeConn(conn) 200 | } 201 | } 202 | 203 | // Serve{{.ServiceName}} serves the given {{.ServiceName}} implementation. 204 | func Serve{{.ServiceName}}(conn io.ReadWriteCloser, x {{.ServiceName}}) { 205 | srv := rpc.NewServer() 206 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 207 | log.Fatal(err) 208 | } 209 | srv.ServeConn(conn) 210 | } 211 | ` 212 | { 213 | out := bytes.NewBuffer([]byte{}) 214 | t := template.Must(template.New("").Parse(serviceHelperFunTmpl)) 215 | t.Execute(out, &struct{ PackageName, ServiceName, ServiceRegisterName string }{ 216 | PackageName: file.GetPackage(), 217 | ServiceName: generator.CamelCase(svc.GetName()), 218 | ServiceRegisterName: p.makeServiceRegisterName( 219 | file, file.GetPackage(), generator.CamelCase(svc.GetName()), 220 | ), 221 | }) 222 | 223 | return out.String() 224 | } 225 | } 226 | 227 | func (p *protorpcPlugin) genServiceClient( 228 | g *generator.Generator, 229 | file *generator.FileDescriptor, 230 | svc *descriptor.ServiceDescriptorProto, 231 | ) string { 232 | const clientHelperFuncTmpl = ` 233 | type {{.ServiceName}}Client struct { 234 | *rpc.Client 235 | } 236 | 237 | // New{{.ServiceName}}Client returns a {{.ServiceName}} stub to handle 238 | // requests to the set of {{.ServiceName}} at the other end of the connection. 239 | func New{{.ServiceName}}Client(conn io.ReadWriteCloser) (*{{.ServiceName}}Client) { 240 | c := rpc.NewClient(conn) 241 | return &{{.ServiceName}}Client{c} 242 | } 243 | 244 | {{.MethodList}} 245 | 246 | // Dial{{.ServiceName}} connects to an {{.ServiceName}} at the specified network address. 247 | func Dial{{.ServiceName}}(network, addr string) (*{{.ServiceName}}Client, error) { 248 | c, err := rpc.Dial(network, addr) 249 | if err != nil { 250 | return nil, err 251 | } 252 | return &{{.ServiceName}}Client{c}, nil 253 | } 254 | 255 | // Dial{{.ServiceName}}Timeout connects to an {{.ServiceName}} at the specified network address. 256 | func Dial{{.ServiceName}}Timeout(network, addr string, timeout time.Duration) (*{{.ServiceName}}Client, error) { 257 | conn, err := net.DialTimeout(network, addr, timeout) 258 | if err != nil { 259 | return nil, err 260 | } 261 | return &{{.ServiceName}}Client{rpc.NewClient(conn)}, nil 262 | } 263 | ` 264 | const clientMethodTmpl = ` 265 | func (c *{{.ServiceName}}Client) {{.MethodName}}(in *{{.ArgsType}}) (out *{{.ReplyType}}, err error) { 266 | if in == nil { 267 | in = new({{.ArgsType}}) 268 | } 269 | 270 | type Validator interface { 271 | Validate() error 272 | } 273 | if x, ok := proto.Message(in).(Validator); ok { 274 | if err := x.Validate(); err != nil { 275 | return nil, err 276 | } 277 | } 278 | 279 | out = new({{.ReplyType}}) 280 | if err = c.Call("{{.ServiceRegisterName}}.{{.MethodName}}", in, out); err != nil { 281 | return nil, err 282 | } 283 | 284 | if x, ok := proto.Message(out).(Validator); ok { 285 | if err := x.Validate(); err != nil { 286 | return out, err 287 | } 288 | } 289 | 290 | return out, nil 291 | } 292 | 293 | func (c *{{.ServiceName}}Client) Async{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}, done chan *rpc.Call) *rpc.Call { 294 | if in == nil { 295 | in = new({{.ArgsType}}) 296 | } 297 | return c.Go( 298 | "{{.ServiceRegisterName}}.{{.MethodName}}", 299 | in, out, 300 | done, 301 | ) 302 | } 303 | ` 304 | 305 | // gen client method list 306 | var methodList string 307 | for _, m := range svc.Method { 308 | out := bytes.NewBuffer([]byte{}) 309 | t := template.Must(template.New("").Parse(clientMethodTmpl)) 310 | t.Execute(out, &struct{ ServiceName, ServiceRegisterName, MethodName, ArgsType, ReplyType string }{ 311 | ServiceName: generator.CamelCase(svc.GetName()), 312 | ServiceRegisterName: p.makeServiceRegisterName( 313 | file, file.GetPackage(), generator.CamelCase(svc.GetName()), 314 | ), 315 | MethodName: generator.CamelCase(m.GetName()), 316 | ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())), 317 | ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())), 318 | }) 319 | methodList += out.String() 320 | } 321 | 322 | // gen all client code 323 | { 324 | out := bytes.NewBuffer([]byte{}) 325 | t := template.Must(template.New("").Parse(clientHelperFuncTmpl)) 326 | t.Execute(out, &struct{ PackageName, ServiceName, MethodList string }{ 327 | PackageName: file.GetPackage(), 328 | ServiceName: generator.CamelCase(svc.GetName()), 329 | MethodList: methodList, 330 | }) 331 | 332 | return out.String() 333 | } 334 | } 335 | 336 | func (p *protorpcPlugin) makeServiceRegisterName( 337 | file *generator.FileDescriptor, 338 | packageName, serviceName string, 339 | ) string { 340 | // return packageName + "." + serviceName 341 | return serviceName 342 | } 343 | -------------------------------------------------------------------------------- /protoc-gen-stdrpc/main.go: -------------------------------------------------------------------------------- 1 | // Go support for Protocol Buffers - Google's data interchange format 2 | // 3 | // Copyright 2010 The Go Authors. All rights reserved. 4 | // https://github.com/golang/protobuf 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are 8 | // met: 9 | // 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above 13 | // copyright notice, this list of conditions and the following disclaimer 14 | // in the documentation and/or other materials provided with the 15 | // distribution. 16 | // * Neither the name of Google Inc. nor the names of its 17 | // contributors may be used to endorse or promote products derived from 18 | // this software without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | // protoc-gen-go is a plugin for the Google protocol buffer compiler to generate 33 | // Go code. Run it by building this program and putting it in your path with 34 | // the name 35 | // protoc-gen-go 36 | // That word 'go' at the end becomes part of the option string set for the 37 | // protocol compiler, so once the protocol compiler (protoc) is installed 38 | // you can run 39 | // protoc --go_out=output_directory input_directory/file.proto 40 | // to generate Go bindings for the protocol defined by file.proto. 41 | // With that input, the output will be written to 42 | // output_directory/file.pb.go 43 | // 44 | // The generated code is documented in the package comment for 45 | // the library. 46 | // 47 | // See the README and documentation for protocol buffers to learn more: 48 | // https://developers.google.com/protocol-buffers/ 49 | package main 50 | 51 | import ( 52 | "io/ioutil" 53 | "os" 54 | "strings" 55 | 56 | "github.com/golang/protobuf/proto" 57 | "github.com/golang/protobuf/protoc-gen-go/generator" 58 | ) 59 | 60 | func main() { 61 | // Begin by allocating a generator. The request and response structures are stored there 62 | // so we can do error handling easily - the response structure contains the field to 63 | // report failure. 64 | g := generator.New() 65 | 66 | data, err := ioutil.ReadAll(os.Stdin) 67 | if err != nil { 68 | g.Error(err, "reading input") 69 | } 70 | 71 | if err := proto.Unmarshal(data, g.Request); err != nil { 72 | g.Error(err, "parsing input proto") 73 | } 74 | 75 | if len(g.Request.FileToGenerate) == 0 { 76 | g.Fail("no files to generate") 77 | } 78 | 79 | parameter := g.Request.GetParameter() 80 | if !strings.Contains(parameter, "plugins=") { 81 | parameter += ",plugins=" + netrpcPluginName 82 | } 83 | g.CommandLineParameters(parameter) 84 | 85 | // Create a wrapped version of the Descriptors and EnumDescriptors that 86 | // point to the file that defines them. 87 | g.WrapTypes() 88 | 89 | g.SetPackageNames() 90 | g.BuildTypeNameMap() 91 | 92 | g.GenerateAllFiles() 93 | 94 | // Send back the results. 95 | data, err = proto.Marshal(g.Response) 96 | if err != nil { 97 | g.Error(err, "failed to marshal output proto") 98 | } 99 | _, err = os.Stdout.Write(data) 100 | if err != nil { 101 | g.Error(err, "failed to write output proto") 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /protoc-gen-stdrpc/netrpc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "bytes" 9 | "text/template" 10 | 11 | "github.com/golang/protobuf/protoc-gen-go/descriptor" 12 | "github.com/golang/protobuf/protoc-gen-go/generator" 13 | ) 14 | 15 | const netrpcPluginName = "netrpc" 16 | 17 | // netrpcPlugin produce the Service interface. 18 | type netrpcPlugin struct { 19 | *generator.Generator 20 | } 21 | 22 | // Name returns the name of the plugin. 23 | func (p *netrpcPlugin) Name() string { return netrpcPluginName } 24 | 25 | // Init is called once after data structures are built but before 26 | // code generation begins. 27 | func (p *netrpcPlugin) Init(g *generator.Generator) { 28 | p.Generator = g 29 | } 30 | 31 | // Generate produces the code generated by the plugin for this file. 32 | func (p *netrpcPlugin) GenerateImports(file *generator.FileDescriptor) { 33 | if len(file.Service) > 0 { 34 | p.P(`import "bufio"`) 35 | p.P(`import "crypto/tls"`) 36 | p.P(`import "errors"`) 37 | p.P(`import "io"`) 38 | p.P(`import "log"`) 39 | p.P(`import "net"`) 40 | p.P(`import "net/http"`) 41 | p.P(`import "net/rpc"`) 42 | p.P(`import "time"`) 43 | } 44 | } 45 | 46 | // Generate generates the Service interface. 47 | // rpc service can't handle other proto message!!! 48 | func (p *netrpcPlugin) Generate(file *generator.FileDescriptor) { 49 | for _, svc := range file.Service { 50 | p.genServiceInterface(file, svc) 51 | p.genServiceServer(file, svc) 52 | p.genServiceClient(file, svc) 53 | } 54 | } 55 | 56 | func (p *netrpcPlugin) genServiceInterface( 57 | file *generator.FileDescriptor, 58 | svc *descriptor.ServiceDescriptorProto, 59 | ) { 60 | const serviceInterfaceTmpl = ` 61 | type {{.ServiceName}} interface { 62 | {{.CallMethodList}} 63 | } 64 | ` 65 | const callMethodTmpl = ` 66 | {{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}) error` 67 | 68 | // gen call method list 69 | var callMethodList string 70 | for _, m := range svc.Method { 71 | out := bytes.NewBuffer([]byte{}) 72 | t := template.Must(template.New("").Parse(callMethodTmpl)) 73 | t.Execute(out, &struct{ ServiceName, MethodName, ArgsType, ReplyType string }{ 74 | ServiceName: generator.CamelCase(svc.GetName()), 75 | MethodName: generator.CamelCase(m.GetName()), 76 | ArgsType: p.TypeName(p.ObjectNamed(m.GetInputType())), 77 | ReplyType: p.TypeName(p.ObjectNamed(m.GetOutputType())), 78 | }) 79 | callMethodList += out.String() 80 | 81 | p.RecordTypeUse(m.GetInputType()) 82 | p.RecordTypeUse(m.GetOutputType()) 83 | } 84 | 85 | // gen all interface code 86 | { 87 | out := bytes.NewBuffer([]byte{}) 88 | t := template.Must(template.New("").Parse(serviceInterfaceTmpl)) 89 | t.Execute(out, &struct{ ServiceName, CallMethodList string }{ 90 | ServiceName: generator.CamelCase(svc.GetName()), 91 | CallMethodList: callMethodList, 92 | }) 93 | p.P(out.String()) 94 | } 95 | } 96 | 97 | func (p *netrpcPlugin) genServiceServer( 98 | file *generator.FileDescriptor, 99 | svc *descriptor.ServiceDescriptorProto, 100 | ) { 101 | const serviceHelperFunTmpl = ` 102 | // Accept{{.ServiceName}}Client accepts connections on the listener and serves requests 103 | // for each incoming connection. Accept blocks; the caller typically 104 | // invokes it in a go statement. 105 | func Accept{{.ServiceName}}Client(lis net.Listener, x {{.ServiceName}}) { 106 | srv := rpc.NewServer() 107 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 108 | log.Fatal(err) 109 | } 110 | 111 | for { 112 | conn, err := lis.Accept() 113 | if err != nil { 114 | log.Fatalf("lis.Accept(): %v\n", err) 115 | } 116 | go srv.ServeConn(conn) 117 | } 118 | } 119 | 120 | // Register{{.ServiceName}} publish the given {{.ServiceName}} implementation on the server. 121 | func Register{{.ServiceName}}(srv *rpc.Server, x {{.ServiceName}}) error { 122 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 123 | return err 124 | } 125 | return nil 126 | } 127 | 128 | // New{{.ServiceName}}Server returns a new {{.ServiceName}} Server. 129 | func New{{.ServiceName}}Server(x {{.ServiceName}}) *rpc.Server { 130 | srv := rpc.NewServer() 131 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 132 | log.Fatal(err) 133 | } 134 | return srv 135 | } 136 | 137 | // ListenAndServe{{.ServiceName}} listen announces on the local network address laddr 138 | // and serves the given {{.ServiceName}} implementation. 139 | func ListenAndServe{{.ServiceName}}(network, addr string, x {{.ServiceName}}) error { 140 | lis, err := net.Listen(network, addr) 141 | if err != nil { 142 | return err 143 | } 144 | defer lis.Close() 145 | 146 | srv := rpc.NewServer() 147 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 148 | return err 149 | } 150 | 151 | for { 152 | conn, err := lis.Accept() 153 | if err != nil { 154 | log.Fatalf("lis.Accept(): %v\n", err) 155 | } 156 | go srv.ServeConn(conn) 157 | } 158 | } 159 | 160 | // Serve{{.ServiceName}} serves the given {{.ServiceName}} implementation. 161 | func Serve{{.ServiceName}}(conn io.ReadWriteCloser, x {{.ServiceName}}) { 162 | srv := rpc.NewServer() 163 | if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil { 164 | log.Fatal(err) 165 | } 166 | srv.ServeConn(conn) 167 | } 168 | ` 169 | { 170 | out := bytes.NewBuffer([]byte{}) 171 | t := template.Must(template.New("").Parse(serviceHelperFunTmpl)) 172 | t.Execute(out, &struct{ PackageName, ServiceName, ServiceRegisterName string }{ 173 | PackageName: file.GetPackage(), 174 | ServiceName: generator.CamelCase(svc.GetName()), 175 | ServiceRegisterName: p.makeServiceRegisterName( 176 | file, file.GetPackage(), generator.CamelCase(svc.GetName()), 177 | ), 178 | }) 179 | p.P(out.String()) 180 | } 181 | } 182 | 183 | func (p *netrpcPlugin) genServiceClient( 184 | file *generator.FileDescriptor, 185 | svc *descriptor.ServiceDescriptorProto, 186 | ) { 187 | const clientHelperFuncTmpl = ` 188 | type {{.ServiceName}}Client struct { 189 | *rpc.Client 190 | } 191 | 192 | // New{{.ServiceName}}Client returns a {{.ServiceName}} stub to handle 193 | // requests to the set of {{.ServiceName}} at the other end of the connection. 194 | func New{{.ServiceName}}Client(conn io.ReadWriteCloser) (*{{.ServiceName}}Client) { 195 | c := rpc.NewClient(conn) 196 | return &{{.ServiceName}}Client{c} 197 | } 198 | 199 | {{.MethodList}} 200 | 201 | // Dial{{.ServiceName}} connects to an {{.ServiceName}} at the specified network address. 202 | func Dial{{.ServiceName}}(network, addr string) (*{{.ServiceName}}Client, error) { 203 | c, err := rpc.Dial(network, addr) 204 | if err != nil { 205 | return nil, err 206 | } 207 | return &{{.ServiceName}}Client{c}, nil 208 | } 209 | 210 | // Dial{{.ServiceName}}Timeout connects to an {{.ServiceName}} at the specified network address. 211 | func Dial{{.ServiceName}}Timeout(network, addr string, timeout time.Duration) (*{{.ServiceName}}Client, error) { 212 | conn, err := net.DialTimeout(network, addr, timeout) 213 | if err != nil { 214 | return nil, err 215 | } 216 | return &{{.ServiceName}}Client{rpc.NewClient(conn)}, nil 217 | } 218 | 219 | // Dial{{.ServiceName}}HTTP connects to an HTTP RPC server at the specified network address 220 | // listening on the default HTTP RPC path. 221 | func Dial{{.ServiceName}}HTTP(network, address string) (*{{.ServiceName}}Client, error) { 222 | return Dial{{.ServiceName}}HTTPPath(network, address, rpc.DefaultRPCPath) 223 | } 224 | 225 | // Dial{{.ServiceName}}HTTPPath connects to an HTTP RPC server 226 | // at the specified network address and path. 227 | func Dial{{.ServiceName}}HTTPPath(network, address, path string) (*{{.ServiceName}}Client, error) { 228 | conn, err := net.Dial(network, address) 229 | if err != nil { 230 | return nil, err 231 | } 232 | return dial{{.ServiceName}}Path(network, address, path, conn) 233 | } 234 | 235 | // Dial{{.ServiceName}}HTTPS connects to an HTTPS RPC server at the specified network address 236 | // listening on the default HTTP RPC path. 237 | func Dial{{.ServiceName}}HTTPS(network, address string, tlsConfig *tls.Config) (*{{.ServiceName}}Client, error) { 238 | return Dial{{.ServiceName}}HTTPSPath(network, address, rpc.DefaultRPCPath, tlsConfig) 239 | } 240 | 241 | // Dial{{.ServiceName}}HTTPSPath connects to an HTTPS RPC server 242 | // at the specified network address and path. 243 | func Dial{{.ServiceName}}HTTPSPath(network, address, path string, tlsConfig *tls.Config) (*{{.ServiceName}}Client, error) { 244 | conn, err := tls.Dial(network, address, tlsConfig) 245 | if err != nil { 246 | return nil, err 247 | } 248 | return dial{{.ServiceName}}Path(network, address, path, conn) 249 | } 250 | 251 | func dial{{.ServiceName}}Path(network, address, path string, conn net.Conn) (*{{.ServiceName}}Client, error) { 252 | const net_rpc_connected = "200 Connected to Go RPC" 253 | 254 | io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n") 255 | 256 | // Require successful HTTP response 257 | // before switching to RPC protocol. 258 | resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"}) 259 | if err == nil && resp.Status == net_rpc_connected { 260 | return &{{.ServiceName}}Client{rpc.NewClient(conn)}, nil 261 | } 262 | if err == nil { 263 | err = errors.New("unexpected HTTP response: " + resp.Status) 264 | } 265 | conn.Close() 266 | return nil, &net.OpError{ 267 | Op: "dial-http", 268 | Net: network + " " + address, 269 | Addr: nil, 270 | Err: err, 271 | } 272 | } 273 | ` 274 | const clientMethodTmpl = ` 275 | func (c *{{.ServiceName}}Client) {{.MethodName}}(in *{{.ArgsType}}) (out *{{.ReplyType}}, err error) { 276 | if in == nil { 277 | in = new({{.ArgsType}}) 278 | } 279 | type Validator interface { 280 | Validate() error 281 | } 282 | if x, ok := proto.Message(in).(Validator); ok { 283 | if err := x.Validate(); err != nil { 284 | return nil, err 285 | } 286 | } 287 | out = new({{.ReplyType}}) 288 | if err = c.Call("{{.ServiceRegisterName}}.{{.MethodName}}", in, out); err != nil { 289 | return nil, err 290 | } 291 | if x, ok := proto.Message(out).(Validator); ok { 292 | if err := x.Validate(); err != nil { 293 | return out, err 294 | } 295 | } 296 | return out, nil 297 | } 298 | 299 | func (c *{{.ServiceName}}Client) Async{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}, done chan *rpc.Call) *rpc.Call { 300 | if in == nil { 301 | in = new({{.ArgsType}}) 302 | } 303 | return c.Go( 304 | "{{.ServiceRegisterName}}.{{.MethodName}}", 305 | in, out, 306 | done, 307 | ) 308 | } 309 | ` 310 | 311 | // gen client method list 312 | var methodList string 313 | for _, m := range svc.Method { 314 | out := bytes.NewBuffer([]byte{}) 315 | t := template.Must(template.New("").Parse(clientMethodTmpl)) 316 | t.Execute(out, &struct{ ServiceName, ServiceRegisterName, MethodName, ArgsType, ReplyType string }{ 317 | ServiceName: generator.CamelCase(svc.GetName()), 318 | ServiceRegisterName: p.makeServiceRegisterName( 319 | file, file.GetPackage(), generator.CamelCase(svc.GetName()), 320 | ), 321 | MethodName: generator.CamelCase(m.GetName()), 322 | ArgsType: p.TypeName(p.ObjectNamed(m.GetInputType())), 323 | ReplyType: p.TypeName(p.ObjectNamed(m.GetOutputType())), 324 | }) 325 | methodList += out.String() 326 | } 327 | 328 | // gen all client code 329 | { 330 | out := bytes.NewBuffer([]byte{}) 331 | t := template.Must(template.New("").Parse(clientHelperFuncTmpl)) 332 | t.Execute(out, &struct{ PackageName, ServiceName, MethodList string }{ 333 | PackageName: file.GetPackage(), 334 | ServiceName: generator.CamelCase(svc.GetName()), 335 | MethodList: methodList, 336 | }) 337 | p.P(out.String()) 338 | } 339 | } 340 | 341 | func (p *netrpcPlugin) makeServiceRegisterName( 342 | file *generator.FileDescriptor, 343 | packageName, serviceName string, 344 | ) string { 345 | return packageName + "." + serviceName 346 | } 347 | 348 | func init() { 349 | generator.RegisterPlugin(new(netrpcPlugin)) 350 | } 351 | -------------------------------------------------------------------------------- /rpc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package protorpc_test 6 | 7 | import ( 8 | "errors" 9 | "log" 10 | "net" 11 | "net/rpc" 12 | "testing" 13 | "time" 14 | 15 | "github.com/chai2010/protorpc" 16 | msg "github.com/chai2010/protorpc/examples/message.pb" 17 | ) 18 | 19 | type Arith int 20 | 21 | func (t *Arith) Add(args *msg.ArithRequest, reply *msg.ArithResponse) error { 22 | reply.C = args.A + args.B 23 | log.Printf("Arith.Add(%v, %v): %v", args.A, args.B, reply.C) 24 | return nil 25 | } 26 | 27 | func (t *Arith) Mul(args *msg.ArithRequest, reply *msg.ArithResponse) error { 28 | reply.C = args.A * args.B 29 | return nil 30 | } 31 | 32 | func (t *Arith) Div(args *msg.ArithRequest, reply *msg.ArithResponse) error { 33 | if args.B == 0 { 34 | return errors.New("divide by zero") 35 | } 36 | reply.C = args.A / args.B 37 | return nil 38 | } 39 | 40 | func (t *Arith) Error(args *msg.ArithRequest, reply *msg.ArithResponse) error { 41 | return errors.New("ArithError") 42 | } 43 | 44 | type Echo int 45 | 46 | func (t *Echo) Echo(args *msg.EchoRequest, reply *msg.EchoResponse) error { 47 | reply.Msg = args.Msg 48 | return nil 49 | } 50 | 51 | func TestInternalMessagePkg(t *testing.T) { 52 | err := listenAndServeArithAndEchoService("tcp", "127.0.0.1:1414") 53 | if err != nil { 54 | log.Fatalf("listenAndServeArithAndEchoService: %v", err) 55 | } 56 | 57 | conn, err := net.Dial("tcp", "127.0.0.1:1414") 58 | if err != nil { 59 | t.Fatalf(`net.Dial("tcp", "127.0.0.1:1414"): %v`, err) 60 | } 61 | client := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn)) 62 | defer client.Close() 63 | 64 | testArithClient(t, client) 65 | testEchoClient(t, client) 66 | 67 | testArithClientAsync(t, client) 68 | testEchoClientAsync(t, client) 69 | } 70 | 71 | func listenAndServeArithAndEchoService(network, addr string) error { 72 | clients, err := net.Listen(network, addr) 73 | if err != nil { 74 | return err 75 | } 76 | srv := rpc.NewServer() 77 | if err := srv.RegisterName("ArithService", new(Arith)); err != nil { 78 | return err 79 | } 80 | if err := srv.RegisterName("EchoService", new(Echo)); err != nil { 81 | return err 82 | } 83 | go func() { 84 | for { 85 | conn, err := clients.Accept() 86 | if err != nil { 87 | log.Printf("clients.Accept(): %v\n", err) 88 | continue 89 | } 90 | go srv.ServeCodec(protorpc.NewServerCodec(conn)) 91 | } 92 | }() 93 | return nil 94 | } 95 | 96 | func testArithClient(t *testing.T, client *rpc.Client) { 97 | var args msg.ArithRequest 98 | var reply msg.ArithResponse 99 | var err error 100 | 101 | // Add 102 | args.A = 1 103 | args.B = 2 104 | if err = client.Call("ArithService.Add", &args, &reply); err != nil { 105 | t.Fatalf(`arith.Add: %v`, err) 106 | } 107 | if reply.C != 3 { 108 | t.Fatalf(`arith.Add: expected = %d, got = %d`, 3, reply.C) 109 | } 110 | 111 | // Mul 112 | args.A = 2 113 | args.B = 3 114 | if err = client.Call("ArithService.Mul", &args, &reply); err != nil { 115 | t.Fatalf(`arith.Mul: %v`, err) 116 | } 117 | if reply.C != 6 { 118 | t.Fatalf(`arith.Mul: expected = %d, got = %d`, 6, reply.C) 119 | } 120 | 121 | // Div 122 | args.A = 13 123 | args.B = 5 124 | if err = client.Call("ArithService.Div", &args, &reply); err != nil { 125 | t.Fatalf(`arith.Div: %v`, err) 126 | } 127 | if reply.C != 2 { 128 | t.Fatalf(`arith.Div: expected = %d, got = %d`, 2, reply.C) 129 | } 130 | 131 | // Div zero 132 | args.A = 1 133 | args.B = 0 134 | if err = client.Call("ArithService.Div", &args, &reply); err.Error() != "divide by zero" { 135 | t.Fatalf(`arith.Error: expected = "%s", got = "%s"`, "divide by zero", err.Error()) 136 | } 137 | 138 | // Error 139 | args.A = 1 140 | args.B = 2 141 | if err = client.Call("ArithService.Error", &args, &reply); err.Error() != "ArithError" { 142 | t.Fatalf(`arith.Error: expected = "%s", got = "%s"`, "ArithError", err.Error()) 143 | } 144 | } 145 | 146 | func testArithClientAsync(t *testing.T, client *rpc.Client) { 147 | done := make(chan *rpc.Call, 16) 148 | callInfoList := []struct { 149 | method string 150 | args *msg.ArithRequest 151 | reply *msg.ArithResponse 152 | err error 153 | }{ 154 | { 155 | "ArithService.Add", 156 | &msg.ArithRequest{A: 1, B: 2}, 157 | &msg.ArithResponse{C: 3}, 158 | nil, 159 | }, 160 | { 161 | "ArithService.Mul", 162 | &msg.ArithRequest{A: 2, B: 3}, 163 | &msg.ArithResponse{C: 6}, 164 | nil, 165 | }, 166 | { 167 | "ArithService.Div", 168 | &msg.ArithRequest{A: 13, B: 5}, 169 | &msg.ArithResponse{C: 2}, 170 | nil, 171 | }, 172 | { 173 | "ArithService.Div", 174 | &msg.ArithRequest{A: 1, B: 0}, 175 | &msg.ArithResponse{}, 176 | errors.New("divide by zero"), 177 | }, 178 | { 179 | "ArithService.Error", 180 | &msg.ArithRequest{A: 1, B: 2}, 181 | &msg.ArithResponse{}, 182 | errors.New("ArithError"), 183 | }, 184 | } 185 | 186 | // GoCall list 187 | calls := make([]*rpc.Call, len(callInfoList)) 188 | for i := 0; i < len(calls); i++ { 189 | calls[i] = client.Go(callInfoList[i].method, 190 | callInfoList[i].args, callInfoList[i].reply, 191 | done, 192 | ) 193 | } 194 | for i := 0; i < len(calls); i++ { 195 | <-calls[i].Done 196 | } 197 | 198 | // check result 199 | for i := 0; i < len(calls); i++ { 200 | if callInfoList[i].err != nil { 201 | if calls[i].Error.Error() != callInfoList[i].err.Error() { 202 | t.Fatalf(`%s: expected %v, Got = %v`, 203 | callInfoList[i].method, 204 | callInfoList[i].err, 205 | calls[i].Error, 206 | ) 207 | } 208 | continue 209 | } 210 | 211 | got := calls[i].Reply.(*msg.ArithResponse).C 212 | expected := callInfoList[i].reply.C 213 | if got != expected { 214 | t.Fatalf(`%v: expected %v, Got = %v`, 215 | callInfoList[i].method, got, expected, 216 | ) 217 | } 218 | } 219 | } 220 | 221 | func testEchoClient(t *testing.T, client *rpc.Client) { 222 | var args msg.EchoRequest 223 | var reply msg.EchoResponse 224 | var err error 225 | 226 | // EchoService.Echo 227 | args.Msg = "Hello, Protobuf-RPC" 228 | if err = client.Call("EchoService.Echo", &args, &reply); err != nil { 229 | t.Fatalf(`EchoService.Echo: %v`, err) 230 | } 231 | if reply.Msg != args.Msg { 232 | t.Fatalf(`EchoService.Echo: expected = "%s", got = "%s"`, args.Msg, reply.Msg) 233 | } 234 | } 235 | 236 | func testEchoClientAsync(t *testing.T, client *rpc.Client) { 237 | // EchoService.Echo 238 | args := &msg.EchoRequest{Msg: "Hello, Protobuf-RPC"} 239 | reply := &msg.EchoResponse{} 240 | echoCall := client.Go("EchoService.Echo", args, reply, nil) 241 | 242 | // sleep 1s 243 | time.Sleep(time.Second) 244 | 245 | // EchoService.Echo reply 246 | echoCall = <-echoCall.Done 247 | if echoCall.Error != nil { 248 | t.Fatalf(`EchoService.Echo: %v`, echoCall.Error) 249 | } 250 | if echoCall.Reply.(*msg.EchoResponse).Msg != args.Msg { 251 | t.Fatalf(`EchoService.Echo: expected = "%s", got = "%s"`, 252 | args.Msg, 253 | echoCall.Reply.(*msg.EchoResponse).Msg, 254 | ) 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package protorpc 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | "io" 11 | "net/rpc" 12 | "sync" 13 | 14 | wire "github.com/chai2010/protorpc/wire.pb" 15 | "github.com/golang/protobuf/proto" 16 | ) 17 | 18 | type serverCodec struct { 19 | r io.Reader 20 | w io.Writer 21 | c io.Closer 22 | 23 | // temporary work space 24 | reqHeader wire.RequestHeader 25 | 26 | // Package rpc expects uint64 request IDs. 27 | // We assign uint64 sequence numbers to incoming requests 28 | // but save the original request ID in the pending map. 29 | // When rpc responds, we use the sequence number in 30 | // the response to find the original request ID. 31 | mutex sync.Mutex // protects seq, pending 32 | seq uint64 33 | pending map[uint64]uint64 34 | } 35 | 36 | // NewServerCodec returns a serverCodec that communicates with the ClientCodec 37 | // on the other end of the given conn. 38 | func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec { 39 | return &serverCodec{ 40 | r: conn, 41 | w: conn, 42 | c: conn, 43 | pending: make(map[uint64]uint64), 44 | } 45 | } 46 | 47 | func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error { 48 | header := wire.RequestHeader{} 49 | err := readRequestHeader(c.r, &header) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | c.mutex.Lock() 55 | c.seq++ 56 | c.pending[c.seq] = header.Id 57 | r.ServiceMethod = header.Method 58 | r.Seq = c.seq 59 | c.mutex.Unlock() 60 | 61 | c.reqHeader = header 62 | return nil 63 | } 64 | 65 | func (c *serverCodec) ReadRequestBody(x interface{}) error { 66 | if x == nil { 67 | return nil 68 | } 69 | request, ok := x.(proto.Message) 70 | if !ok { 71 | return fmt.Errorf( 72 | "protorpc.ServerCodec.ReadRequestBody: %T does not implement proto.Message", 73 | x, 74 | ) 75 | } 76 | 77 | err := readRequestBody(c.r, &c.reqHeader, request) 78 | if err != nil { 79 | return nil 80 | } 81 | 82 | c.reqHeader = wire.RequestHeader{} 83 | return nil 84 | } 85 | 86 | // A value sent as a placeholder for the server's response value when the server 87 | // receives an invalid request. It is never decoded by the client since the Response 88 | // contains an error when it is used. 89 | var invalidRequest = struct{}{} 90 | 91 | func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error { 92 | var response proto.Message 93 | if x != nil { 94 | var ok bool 95 | if response, ok = x.(proto.Message); !ok { 96 | if _, ok = x.(struct{}); !ok { 97 | c.mutex.Lock() 98 | delete(c.pending, r.Seq) 99 | c.mutex.Unlock() 100 | return fmt.Errorf( 101 | "protorpc.ServerCodec.WriteResponse: %T does not implement proto.Message", 102 | x, 103 | ) 104 | } 105 | } 106 | } 107 | 108 | c.mutex.Lock() 109 | id, ok := c.pending[r.Seq] 110 | if !ok { 111 | c.mutex.Unlock() 112 | return errors.New("protorpc: invalid sequence number in response") 113 | } 114 | delete(c.pending, r.Seq) 115 | c.mutex.Unlock() 116 | 117 | err := writeResponse(c.w, id, r.Error, response) 118 | if err != nil { 119 | return err 120 | } 121 | 122 | return nil 123 | } 124 | 125 | func (s *serverCodec) Close() error { 126 | return s.c.Close() 127 | } 128 | 129 | // ServeConn runs the Protobuf-RPC server on a single connection. 130 | // ServeConn blocks, serving the connection until the client hangs up. 131 | // The caller typically invokes ServeConn in a go statement. 132 | func ServeConn(conn io.ReadWriteCloser) { 133 | rpc.ServeCodec(NewServerCodec(conn)) 134 | } 135 | -------------------------------------------------------------------------------- /wire.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package protorpc 6 | 7 | import ( 8 | "fmt" 9 | "hash/crc32" 10 | "io" 11 | 12 | wire "github.com/chai2010/protorpc/wire.pb" 13 | "github.com/golang/protobuf/proto" 14 | "github.com/golang/snappy" 15 | ) 16 | 17 | var ( 18 | UseSnappy = true 19 | UseCrc32ChecksumIEEE = true 20 | ) 21 | 22 | func maxUint32(a, b uint32) uint32 { 23 | if a > b { 24 | return a 25 | } 26 | return b 27 | } 28 | 29 | func writeRequest(w io.Writer, id uint64, method string, request proto.Message) error { 30 | // marshal request 31 | pbRequest := []byte{} 32 | if request != nil { 33 | var err error 34 | pbRequest, err = proto.Marshal(request) 35 | if err != nil { 36 | return err 37 | } 38 | } 39 | 40 | // compress serialized proto data 41 | compressedPbRequest := snappy.Encode(nil, pbRequest) 42 | 43 | // generate header 44 | header := &wire.RequestHeader{ 45 | Id: id, 46 | Method: method, 47 | RawRequestLen: uint32(len(pbRequest)), 48 | SnappyCompressedRequestLen: uint32(len(compressedPbRequest)), 49 | Checksum: crc32.ChecksumIEEE(compressedPbRequest), 50 | } 51 | 52 | if !UseSnappy { 53 | header.SnappyCompressedRequestLen = 0 54 | compressedPbRequest = pbRequest 55 | } 56 | if !UseCrc32ChecksumIEEE { 57 | header.Checksum = 0 58 | } 59 | 60 | // check header size 61 | pbHeader, err := proto.Marshal(header) 62 | if err != err { 63 | return err 64 | } 65 | if len(pbHeader) > int(wire.Const_MAX_REQUEST_HEADER_LEN) { 66 | return fmt.Errorf("protorpc.writeRequest: header larger than max_header_len: %d.", len(pbHeader)) 67 | } 68 | 69 | // send header (more) 70 | if err := sendFrame(w, pbHeader); err != nil { 71 | return err 72 | } 73 | 74 | // send body (end) 75 | if err := sendFrame(w, compressedPbRequest); err != nil { 76 | return err 77 | } 78 | 79 | return nil 80 | } 81 | 82 | func readRequestHeader(r io.Reader, header *wire.RequestHeader) (err error) { 83 | // recv header (more) 84 | pbHeader, err := recvFrame(r, int(wire.Const_MAX_REQUEST_HEADER_LEN)) 85 | if err != nil { 86 | return err 87 | } 88 | 89 | // Marshal Header 90 | err = proto.Unmarshal(pbHeader, header) 91 | if err != nil { 92 | return err 93 | } 94 | 95 | return nil 96 | } 97 | 98 | func readRequestBody(r io.Reader, header *wire.RequestHeader, request proto.Message) error { 99 | maxBodyLen := maxUint32(header.RawRequestLen, header.SnappyCompressedRequestLen) 100 | 101 | // recv body (end) 102 | compressedPbRequest, err := recvFrame(r, int(maxBodyLen)) 103 | if err != nil { 104 | return err 105 | } 106 | 107 | // checksum 108 | if header.Checksum != 0 { 109 | if crc32.ChecksumIEEE(compressedPbRequest) != header.Checksum { 110 | return fmt.Errorf("protorpc.readRequestBody: unexpected checksum.") 111 | } 112 | } 113 | 114 | var pbRequest []byte 115 | if header.SnappyCompressedRequestLen != 0 { 116 | // decode the compressed data 117 | pbRequest, err = snappy.Decode(nil, compressedPbRequest) 118 | if err != nil { 119 | return err 120 | } 121 | // check wire header: rawMsgLen 122 | if uint32(len(pbRequest)) != header.RawRequestLen { 123 | return fmt.Errorf("protorpc.readRequestBody: Unexcpeted header.RawRequestLen.") 124 | } 125 | } else { 126 | pbRequest = compressedPbRequest 127 | } 128 | 129 | // Unmarshal to proto message 130 | if request != nil { 131 | err = proto.Unmarshal(pbRequest, request) 132 | if err != nil { 133 | return err 134 | } 135 | } 136 | 137 | return nil 138 | } 139 | 140 | func writeResponse(w io.Writer, id uint64, serr string, response proto.Message) (err error) { 141 | // clean response if error 142 | if serr != "" { 143 | response = nil 144 | } 145 | 146 | // marshal response 147 | pbResponse := []byte{} 148 | if response != nil { 149 | pbResponse, err = proto.Marshal(response) 150 | if err != nil { 151 | return err 152 | } 153 | } 154 | 155 | // compress serialized proto data 156 | compressedPbResponse := snappy.Encode(nil, pbResponse) 157 | 158 | // generate header 159 | header := &wire.ResponseHeader{ 160 | Id: id, 161 | Error: serr, 162 | RawResponseLen: uint32(len(pbResponse)), 163 | SnappyCompressedResponseLen: uint32(len(compressedPbResponse)), 164 | Checksum: crc32.ChecksumIEEE(compressedPbResponse), 165 | } 166 | 167 | if !UseSnappy { 168 | header.SnappyCompressedResponseLen = 0 169 | compressedPbResponse = pbResponse 170 | } 171 | if !UseCrc32ChecksumIEEE { 172 | header.Checksum = 0 173 | } 174 | 175 | // check header size 176 | pbHeader, err := proto.Marshal(header) 177 | if err != err { 178 | return 179 | } 180 | 181 | // send header (more) 182 | if err = sendFrame(w, pbHeader); err != nil { 183 | return 184 | } 185 | 186 | // send body (end) 187 | if err = sendFrame(w, compressedPbResponse); err != nil { 188 | return 189 | } 190 | 191 | return nil 192 | } 193 | 194 | func readResponseHeader(r io.Reader, header *wire.ResponseHeader) error { 195 | // recv header (more) 196 | pbHeader, err := recvFrame(r, 0) 197 | if err != nil { 198 | return err 199 | } 200 | 201 | // Marshal Header 202 | err = proto.Unmarshal(pbHeader, header) 203 | if err != nil { 204 | return err 205 | } 206 | 207 | return nil 208 | } 209 | 210 | func readResponseBody(r io.Reader, header *wire.ResponseHeader, response proto.Message) error { 211 | maxBodyLen := int(maxUint32(header.RawResponseLen, header.SnappyCompressedResponseLen)) 212 | 213 | // recv body (end) 214 | compressedPbResponse, err := recvFrame(r, maxBodyLen) 215 | if err != nil { 216 | return err 217 | } 218 | 219 | // checksum 220 | if header.Checksum != 0 { 221 | if crc32.ChecksumIEEE(compressedPbResponse) != header.Checksum { 222 | return fmt.Errorf("protorpc.readResponseBody: unexpected checksum.") 223 | } 224 | } 225 | 226 | var pbResponse []byte 227 | if header.SnappyCompressedResponseLen != 0 { 228 | // decode the compressed data 229 | pbResponse, err = snappy.Decode(nil, compressedPbResponse) 230 | if err != nil { 231 | return err 232 | } 233 | // check wire header: rawMsgLen 234 | if uint32(len(pbResponse)) != header.RawResponseLen { 235 | return fmt.Errorf("protorpc.readResponseBody: Unexcpeted header.RawResponseLen.") 236 | } 237 | } else { 238 | pbResponse = compressedPbResponse 239 | } 240 | 241 | // Unmarshal to proto message 242 | if response != nil { 243 | err = proto.Unmarshal(pbResponse, response) 244 | if err != nil { 245 | return err 246 | } 247 | } 248 | 249 | return nil 250 | } 251 | -------------------------------------------------------------------------------- /wire.pb/proto.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate protoc --go_out=. wire.proto 6 | 7 | package protorpc_wire 8 | -------------------------------------------------------------------------------- /wire.pb/wire.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: wire.proto 3 | 4 | /* 5 | Package protorpc_wire is a generated protocol buffer package. 6 | 7 | 8 | protorpc wire format wrapper 9 | 10 | 0. Frame Format 11 | len : uvarint64 12 | data: byte[len] 13 | 14 | 1. Client Send Request 15 | Send RequestHeader: sendFrame(zsock, hdr, len(hdr)) 16 | Send Request: sendFrame(zsock, body, hdr.snappy_compressed_request_len) 17 | 18 | 2. Server Recv Request 19 | Recv RequestHeader: recvFrame(zsock, hdr, max_hdr_len, 0) 20 | Recv Request: recvFrame(zsock, body, hdr.snappy_compressed_request_len, 0) 21 | 22 | 3. Server Send Response 23 | Send ResponseHeader: sendFrame(zsock, hdr, len(hdr)) 24 | Send Response: sendFrame(zsock, body, hdr.snappy_compressed_response_len) 25 | 26 | 4. Client Recv Response 27 | Recv ResponseHeader: recvFrame(zsock, hdr, max_hdr_len, 0) 28 | Recv Response: recvFrame(zsock, body, hdr.snappy_compressed_response_len, 0) 29 | 30 | 31 | It is generated from these files: 32 | wire.proto 33 | 34 | It has these top-level messages: 35 | RequestHeader 36 | ResponseHeader 37 | */ 38 | package protorpc_wire 39 | 40 | import proto "github.com/golang/protobuf/proto" 41 | import fmt "fmt" 42 | import math "math" 43 | 44 | // Reference imports to suppress errors if they are not otherwise used. 45 | var _ = proto.Marshal 46 | var _ = fmt.Errorf 47 | var _ = math.Inf 48 | 49 | // This is a compile-time assertion to ensure that this generated file 50 | // is compatible with the proto package it is being compiled against. 51 | // A compilation error at this line likely means your copy of the 52 | // proto package needs to be updated. 53 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 54 | 55 | type Const int32 56 | 57 | const ( 58 | Const_ZERO Const = 0 59 | Const_MAX_REQUEST_HEADER_LEN Const = 1024 60 | ) 61 | 62 | var Const_name = map[int32]string{ 63 | 0: "ZERO", 64 | 1024: "MAX_REQUEST_HEADER_LEN", 65 | } 66 | var Const_value = map[string]int32{ 67 | "ZERO": 0, 68 | "MAX_REQUEST_HEADER_LEN": 1024, 69 | } 70 | 71 | func (x Const) String() string { 72 | return proto.EnumName(Const_name, int32(x)) 73 | } 74 | func (Const) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 75 | 76 | type RequestHeader struct { 77 | Id uint64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"` 78 | Method string `protobuf:"bytes,2,opt,name=method" json:"method,omitempty"` 79 | RawRequestLen uint32 `protobuf:"varint,3,opt,name=raw_request_len,json=rawRequestLen" json:"raw_request_len,omitempty"` 80 | SnappyCompressedRequestLen uint32 `protobuf:"varint,4,opt,name=snappy_compressed_request_len,json=snappyCompressedRequestLen" json:"snappy_compressed_request_len,omitempty"` 81 | Checksum uint32 `protobuf:"varint,5,opt,name=checksum" json:"checksum,omitempty"` 82 | } 83 | 84 | func (m *RequestHeader) Reset() { *m = RequestHeader{} } 85 | func (m *RequestHeader) String() string { return proto.CompactTextString(m) } 86 | func (*RequestHeader) ProtoMessage() {} 87 | func (*RequestHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 88 | 89 | func (m *RequestHeader) GetId() uint64 { 90 | if m != nil { 91 | return m.Id 92 | } 93 | return 0 94 | } 95 | 96 | func (m *RequestHeader) GetMethod() string { 97 | if m != nil { 98 | return m.Method 99 | } 100 | return "" 101 | } 102 | 103 | func (m *RequestHeader) GetRawRequestLen() uint32 { 104 | if m != nil { 105 | return m.RawRequestLen 106 | } 107 | return 0 108 | } 109 | 110 | func (m *RequestHeader) GetSnappyCompressedRequestLen() uint32 { 111 | if m != nil { 112 | return m.SnappyCompressedRequestLen 113 | } 114 | return 0 115 | } 116 | 117 | func (m *RequestHeader) GetChecksum() uint32 { 118 | if m != nil { 119 | return m.Checksum 120 | } 121 | return 0 122 | } 123 | 124 | type ResponseHeader struct { 125 | Id uint64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"` 126 | Error string `protobuf:"bytes,2,opt,name=error" json:"error,omitempty"` 127 | RawResponseLen uint32 `protobuf:"varint,3,opt,name=raw_response_len,json=rawResponseLen" json:"raw_response_len,omitempty"` 128 | SnappyCompressedResponseLen uint32 `protobuf:"varint,4,opt,name=snappy_compressed_response_len,json=snappyCompressedResponseLen" json:"snappy_compressed_response_len,omitempty"` 129 | Checksum uint32 `protobuf:"varint,5,opt,name=checksum" json:"checksum,omitempty"` 130 | } 131 | 132 | func (m *ResponseHeader) Reset() { *m = ResponseHeader{} } 133 | func (m *ResponseHeader) String() string { return proto.CompactTextString(m) } 134 | func (*ResponseHeader) ProtoMessage() {} 135 | func (*ResponseHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } 136 | 137 | func (m *ResponseHeader) GetId() uint64 { 138 | if m != nil { 139 | return m.Id 140 | } 141 | return 0 142 | } 143 | 144 | func (m *ResponseHeader) GetError() string { 145 | if m != nil { 146 | return m.Error 147 | } 148 | return "" 149 | } 150 | 151 | func (m *ResponseHeader) GetRawResponseLen() uint32 { 152 | if m != nil { 153 | return m.RawResponseLen 154 | } 155 | return 0 156 | } 157 | 158 | func (m *ResponseHeader) GetSnappyCompressedResponseLen() uint32 { 159 | if m != nil { 160 | return m.SnappyCompressedResponseLen 161 | } 162 | return 0 163 | } 164 | 165 | func (m *ResponseHeader) GetChecksum() uint32 { 166 | if m != nil { 167 | return m.Checksum 168 | } 169 | return 0 170 | } 171 | 172 | func init() { 173 | proto.RegisterType((*RequestHeader)(nil), "protorpc.wire.RequestHeader") 174 | proto.RegisterType((*ResponseHeader)(nil), "protorpc.wire.ResponseHeader") 175 | proto.RegisterEnum("protorpc.wire.Const", Const_name, Const_value) 176 | } 177 | 178 | func init() { proto.RegisterFile("wire.proto", fileDescriptor0) } 179 | 180 | var fileDescriptor0 = []byte{ 181 | // 292 bytes of a gzipped FileDescriptorProto 182 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x5f, 0x4b, 0xf3, 0x30, 183 | 0x14, 0xc6, 0xdf, 0xec, 0xdd, 0xc6, 0x3c, 0xd0, 0x5a, 0x82, 0x8c, 0xb2, 0xa1, 0x94, 0x5d, 0x48, 184 | 0xf1, 0xa2, 0x37, 0x7e, 0x82, 0x52, 0x03, 0xbb, 0x98, 0x8a, 0x51, 0x41, 0xbc, 0x09, 0xb5, 0x3d, 185 | 0xb0, 0xa2, 0x6d, 0x62, 0xd2, 0x51, 0xbc, 0xf3, 0x93, 0x09, 0x7e, 0x33, 0x59, 0x53, 0x66, 0xc5, 186 | 0x3f, 0x57, 0xe1, 0x1c, 0x9e, 0xdf, 0x93, 0xfc, 0x08, 0x40, 0x53, 0x68, 0x8c, 0x94, 0x96, 0xb5, 187 | 0xa4, 0x4e, 0x7b, 0x68, 0x95, 0x45, 0xdb, 0xe5, 0xe2, 0x8d, 0x80, 0xc3, 0xf1, 0x79, 0x83, 0xa6, 188 | 0x5e, 0x62, 0x9a, 0xa3, 0xa6, 0x2e, 0x0c, 0x8a, 0xdc, 0x27, 0x01, 0x09, 0x87, 0x7c, 0x50, 0xe4, 189 | 0x74, 0x0a, 0xe3, 0x12, 0xeb, 0xb5, 0xcc, 0xfd, 0x41, 0x40, 0xc2, 0x3d, 0xde, 0x4d, 0xf4, 0x18, 190 | 0xf6, 0x75, 0xda, 0x08, 0x6d, 0x61, 0xf1, 0x84, 0x95, 0xff, 0x3f, 0x20, 0xa1, 0xc3, 0x1d, 0x9d, 191 | 0x36, 0x5d, 0xe5, 0x0a, 0x2b, 0x1a, 0xc3, 0xa1, 0xa9, 0x52, 0xa5, 0x5e, 0x44, 0x26, 0x4b, 0xa5, 192 | 0xd1, 0x18, 0xcc, 0xbf, 0x50, 0xc3, 0x96, 0x9a, 0xd9, 0x50, 0xb2, 0xcb, 0xf4, 0x2a, 0x66, 0x30, 193 | 0xc9, 0xd6, 0x98, 0x3d, 0x9a, 0x4d, 0xe9, 0x8f, 0xda, 0xf4, 0x6e, 0x5e, 0xbc, 0x13, 0x70, 0x39, 194 | 0x1a, 0x25, 0x2b, 0x83, 0xbf, 0x18, 0x1c, 0xc0, 0x08, 0xb5, 0x96, 0xba, 0x13, 0xb0, 0x03, 0x0d, 195 | 0xc1, 0xb3, 0xef, 0xb7, 0x6c, 0x4f, 0xc0, 0x6d, 0x05, 0xec, 0x7a, 0x7b, 0x7d, 0x02, 0x47, 0x3f, 196 | 0x19, 0xf4, 0x38, 0xab, 0x30, 0xff, 0xae, 0xf0, 0x59, 0xf2, 0x87, 0xc3, 0x49, 0x04, 0xa3, 0x44, 197 | 0x56, 0xa6, 0xa6, 0x13, 0x18, 0xde, 0x33, 0x7e, 0xe9, 0xfd, 0xa3, 0x73, 0x98, 0x9e, 0xc7, 0x77, 198 | 0x82, 0xb3, 0xab, 0x5b, 0x76, 0x7d, 0x23, 0x96, 0x2c, 0x3e, 0x63, 0x5c, 0xac, 0xd8, 0x85, 0xf7, 199 | 0x3a, 0x79, 0x18, 0xb7, 0x7f, 0x78, 0xfa, 0x11, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x10, 0xb3, 0xa4, 200 | 0xd8, 0x01, 0x00, 0x00, 201 | } 202 | -------------------------------------------------------------------------------- /wire.pb/wire.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | syntax = "proto3"; 6 | 7 | // 8 | // protorpc wire format wrapper 9 | // 10 | // 0. Frame Format 11 | // len : uvarint64 12 | // data: byte[len] 13 | // 14 | // 1. Client Send Request 15 | // Send RequestHeader: sendFrame(zsock, hdr, len(hdr)) 16 | // Send Request: sendFrame(zsock, body, hdr.snappy_compressed_request_len) 17 | // 18 | // 2. Server Recv Request 19 | // Recv RequestHeader: recvFrame(zsock, hdr, max_hdr_len, 0) 20 | // Recv Request: recvFrame(zsock, body, hdr.snappy_compressed_request_len, 0) 21 | // 22 | // 3. Server Send Response 23 | // Send ResponseHeader: sendFrame(zsock, hdr, len(hdr)) 24 | // Send Response: sendFrame(zsock, body, hdr.snappy_compressed_response_len) 25 | // 26 | // 4. Client Recv Response 27 | // Recv ResponseHeader: recvFrame(zsock, hdr, max_hdr_len, 0) 28 | // Recv Response: recvFrame(zsock, body, hdr.snappy_compressed_response_len, 0) 29 | // 30 | package protorpc.wire; 31 | 32 | enum Const { 33 | ZERO = 0; 34 | MAX_REQUEST_HEADER_LEN = 1024; 35 | } 36 | 37 | message RequestHeader { 38 | uint64 id = 1; 39 | string method = 2; 40 | 41 | uint32 raw_request_len = 3; 42 | uint32 snappy_compressed_request_len = 4; 43 | uint32 checksum = 5; 44 | } 45 | 46 | message ResponseHeader { 47 | uint64 id = 1; 48 | string error = 2; 49 | 50 | uint32 raw_response_len = 3; 51 | uint32 snappy_compressed_response_len = 4; 52 | uint32 checksum = 5; 53 | } 54 | --------------------------------------------------------------------------------