1
2
3
4
5 package jsonrpc2
6
7 import (
8 "bufio"
9 "context"
10 "encoding/json"
11 "fmt"
12 "io"
13 "strconv"
14 "strings"
15 )
16
17
18
19
20
21
22
23 type Reader interface {
24
25 Read(context.Context) (Message, int64, error)
26 }
27
28
29
30
31
32
33
34 type Writer interface {
35
36 Write(context.Context, Message) (int64, error)
37 }
38
39
40
41
42 type Framer interface {
43
44 Reader(rw io.Reader) Reader
45
46 Writer(rw io.Writer) Writer
47 }
48
49
50
51
52 func RawFramer() Framer { return rawFramer{} }
53
54 type rawFramer struct{}
55 type rawReader struct{ in *json.Decoder }
56 type rawWriter struct{ out io.Writer }
57
58 func (rawFramer) Reader(rw io.Reader) Reader {
59 return &rawReader{in: json.NewDecoder(rw)}
60 }
61
62 func (rawFramer) Writer(rw io.Writer) Writer {
63 return &rawWriter{out: rw}
64 }
65
66 func (r *rawReader) Read(ctx context.Context) (Message, int64, error) {
67 select {
68 case <-ctx.Done():
69 return nil, 0, ctx.Err()
70 default:
71 }
72 var raw json.RawMessage
73 if err := r.in.Decode(&raw); err != nil {
74 return nil, 0, err
75 }
76 msg, err := DecodeMessage(raw)
77 return msg, int64(len(raw)), err
78 }
79
80 func (w *rawWriter) Write(ctx context.Context, msg Message) (int64, error) {
81 select {
82 case <-ctx.Done():
83 return 0, ctx.Err()
84 default:
85 }
86 data, err := EncodeMessage(msg)
87 if err != nil {
88 return 0, fmt.Errorf("marshaling message: %v", err)
89 }
90 n, err := w.out.Write(data)
91 return int64(n), err
92 }
93
94
95
96
97 func HeaderFramer() Framer { return headerFramer{} }
98
99 type headerFramer struct{}
100 type headerReader struct{ in *bufio.Reader }
101 type headerWriter struct{ out io.Writer }
102
103 func (headerFramer) Reader(rw io.Reader) Reader {
104 return &headerReader{in: bufio.NewReader(rw)}
105 }
106
107 func (headerFramer) Writer(rw io.Writer) Writer {
108 return &headerWriter{out: rw}
109 }
110
111 func (r *headerReader) Read(ctx context.Context) (Message, int64, error) {
112 select {
113 case <-ctx.Done():
114 return nil, 0, ctx.Err()
115 default:
116 }
117 var total, length int64
118
119 for {
120 line, err := r.in.ReadString('\n')
121 total += int64(len(line))
122 if err != nil {
123 if err == io.EOF {
124 if total == 0 {
125 return nil, 0, io.EOF
126 }
127 err = io.ErrUnexpectedEOF
128 }
129 return nil, total, fmt.Errorf("failed reading header line: %w", err)
130 }
131 line = strings.TrimSpace(line)
132
133 if line == "" {
134 break
135 }
136 colon := strings.IndexRune(line, ':')
137 if colon < 0 {
138 return nil, total, fmt.Errorf("invalid header line %q", line)
139 }
140 name, value := line[:colon], strings.TrimSpace(line[colon+1:])
141 switch name {
142 case "Content-Length":
143 if length, err = strconv.ParseInt(value, 10, 32); err != nil {
144 return nil, total, fmt.Errorf("failed parsing Content-Length: %v", value)
145 }
146 if length <= 0 {
147 return nil, total, fmt.Errorf("invalid Content-Length: %v", length)
148 }
149 default:
150
151 }
152 }
153 if length == 0 {
154 return nil, total, fmt.Errorf("missing Content-Length header")
155 }
156 data := make([]byte, length)
157 n, err := io.ReadFull(r.in, data)
158 total += int64(n)
159 if err != nil {
160 return nil, total, err
161 }
162 msg, err := DecodeMessage(data)
163 return msg, total, err
164 }
165
166 func (w *headerWriter) Write(ctx context.Context, msg Message) (int64, error) {
167 select {
168 case <-ctx.Done():
169 return 0, ctx.Err()
170 default:
171 }
172 data, err := EncodeMessage(msg)
173 if err != nil {
174 return 0, fmt.Errorf("marshaling message: %v", err)
175 }
176 n, err := fmt.Fprintf(w.out, "Content-Length: %v\r\n\r\n", len(data))
177 total := int64(n)
178 if err == nil {
179 n, err = w.out.Write(data)
180 total += int64(n)
181 }
182 return total, err
183 }
184
View as plain text