-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.go
110 lines (95 loc) · 2.2 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package stratum
import (
"context"
"encoding/json"
"errors"
"io"
"net/rpc"
"sync"
)
type serverCodec struct {
encmutex sync.Mutex // protects enc
dec *json.Decoder // for reading JSON values
enc *json.Encoder // for writing JSON values
c io.ReadWriteCloser
ctx context.Context
// temporary work space
req serverRequest
}
type serverRequest struct {
Version string `json:"jsonrpc"`
Method string `json:"method"`
Params *json.RawMessage `json:"params"`
ID *json.RawMessage `json:"id"`
}
func (r *serverRequest) reset() {
r.Version = ""
r.Method = ""
r.Params = nil
r.ID = nil
}
func (r *serverRequest) UnmarshalJSON(raw []byte) error {
r.reset()
type req *serverRequest
if err := json.Unmarshal(raw, req(r)); err != nil {
return errors.New("bad request")
}
var o = make(map[string]*json.RawMessage)
if err := json.Unmarshal(raw, &o); err != nil {
return errors.New("bad request")
}
// if o["type"] == nil {
// return errors.New("bad request")
// }
_, okID := o["id"]
_, okParams := o["params"]
// if len(o) == 3 && !(okID || okParams) || len(o) == 4 && !(okID && okParams) || len(o) > 4 {
// return errors.New("bad request")
// }
if okParams {
if r.Params == nil || len(*r.Params) == 0 {
return errors.New("bad request")
}
switch []byte(*r.Params)[0] {
case '[', '{':
default:
return errors.New("bad request")
}
}
if okID && r.ID == nil {
r.ID = &null
}
if okID {
if len(*r.ID) == 0 {
return errors.New("bad request")
}
switch []byte(*r.ID)[0] {
case 't', 'f', '{', '[':
return errors.New("bad request")
}
}
return nil
}
type serverResponse struct {
Version string `json:"jsonrpc"`
ID *json.RawMessage `json:"id"`
Result interface{} `json:"result,omitempty"`
Error interface{} `json:"error,omitempty"`
}
// public API
type Server struct {
*rpc.Server
}
func NewServer() *Server {
s := &Server{
rpc.NewServer(),
}
return s
}
func (s *Server) ServeCodec(codec rpc.ServerCodec) {
// defer codec.Close()
s.Server.ServeCodec(codec)
}
func (s *Server) ServeConn(ctx context.Context, conn io.ReadWriteCloser) {
s.ServeCodec(NewDefaultServerCodecContext(ctx, conn))
}