GoPLS Viewer

Home|gopls/internal/jsonrpc2_v2/frame.go
1// Copyright 2018 The Go Authors. 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
5package jsonrpc2
6
7import (
8    "bufio"
9    "context"
10    "encoding/json"
11    "fmt"
12    "io"
13    "strconv"
14    "strings"
15)
16
17// Reader abstracts the transport mechanics from the JSON RPC protocol.
18// A Conn reads messages from the reader it was provided on construction,
19// and assumes that each call to Read fully transfers a single message,
20// or returns an error.
21// A reader is not safe for concurrent use, it is expected it will be used by
22// a single Conn in a safe manner.
23type Reader interface {
24    // Read gets the next message from the stream.
25    Read(context.Context) (Messageint64error)
26}
27
28// Writer abstracts the transport mechanics from the JSON RPC protocol.
29// A Conn writes messages using the writer it was provided on construction,
30// and assumes that each call to Write fully transfers a single message,
31// or returns an error.
32// A writer is not safe for concurrent use, it is expected it will be used by
33// a single Conn in a safe manner.
34type Writer interface {
35    // Write sends a message to the stream.
36    Write(context.ContextMessage) (int64error)
37}
38
39// Framer wraps low level byte readers and writers into jsonrpc2 message
40// readers and writers.
41// It is responsible for the framing and encoding of messages into wire form.
42type Framer interface {
43    // Reader wraps a byte reader into a message reader.
44    Reader(rw io.ReaderReader
45    // Writer wraps a byte writer into a message writer.
46    Writer(rw io.WriterWriter
47}
48
49// RawFramer returns a new Framer.
50// The messages are sent with no wrapping, and rely on json decode consistency
51// to determine message boundaries.
52func RawFramer() Framer { return rawFramer{} }
53
54type rawFramer struct{}
55type rawReader struct{ in *json.Decoder }
56type rawWriter struct{ out io.Writer }
57
58func (rawFramerReader(rw io.ReaderReader {
59    return &rawReader{injson.NewDecoder(rw)}
60}
61
62func (rawFramerWriter(rw io.WriterWriter {
63    return &rawWriter{outrw}
64}
65
66func (r *rawReaderRead(ctx context.Context) (Messageint64error) {
67    select {
68    case <-ctx.Done():
69        return nil0ctx.Err()
70    default:
71    }
72    var raw json.RawMessage
73    if err := r.in.Decode(&raw); err != nil {
74        return nil0err
75    }
76    msgerr := DecodeMessage(raw)
77    return msgint64(len(raw)), err
78}
79
80func (w *rawWriterWrite(ctx context.Contextmsg Message) (int64error) {
81    select {
82    case <-ctx.Done():
83        return 0ctx.Err()
84    default:
85    }
86    dataerr := EncodeMessage(msg)
87    if err != nil {
88        return 0fmt.Errorf("marshaling message: %v"err)
89    }
90    nerr := w.out.Write(data)
91    return int64(n), err
92}
93
94// HeaderFramer returns a new Framer.
95// The messages are sent with HTTP content length and MIME type headers.
96// This is the format used by LSP and others.
97func HeaderFramer() Framer { return headerFramer{} }
98
99type headerFramer struct{}
100type headerReader struct{ in *bufio.Reader }
101type headerWriter struct{ out io.Writer }
102
103func (headerFramerReader(rw io.ReaderReader {
104    return &headerReader{inbufio.NewReader(rw)}
105}
106
107func (headerFramerWriter(rw io.WriterWriter {
108    return &headerWriter{outrw}
109}
110
111func (r *headerReaderRead(ctx context.Context) (Messageint64error) {
112    select {
113    case <-ctx.Done():
114        return nil0ctx.Err()
115    default:
116    }
117    var totallength int64
118    // read the header, stop on the first empty line
119    for {
120        lineerr := r.in.ReadString('\n')
121        total += int64(len(line))
122        if err != nil {
123            if err == io.EOF {
124                if total == 0 {
125                    return nil0io.EOF
126                }
127                err = io.ErrUnexpectedEOF
128            }
129            return niltotalfmt.Errorf("failed reading header line: %w"err)
130        }
131        line = strings.TrimSpace(line)
132        // check we have a header line
133        if line == "" {
134            break
135        }
136        colon := strings.IndexRune(line':')
137        if colon < 0 {
138            return niltotalfmt.Errorf("invalid header line %q"line)
139        }
140        namevalue := line[:colon], strings.TrimSpace(line[colon+1:])
141        switch name {
142        case "Content-Length":
143            if lengtherr = strconv.ParseInt(value1032); err != nil {
144                return niltotalfmt.Errorf("failed parsing Content-Length: %v"value)
145            }
146            if length <= 0 {
147                return niltotalfmt.Errorf("invalid Content-Length: %v"length)
148            }
149        default:
150            // ignoring unknown headers
151        }
152    }
153    if length == 0 {
154        return niltotalfmt.Errorf("missing Content-Length header")
155    }
156    data := make([]bytelength)
157    nerr := io.ReadFull(r.indata)
158    total += int64(n)
159    if err != nil {
160        return niltotalerr
161    }
162    msgerr := DecodeMessage(data)
163    return msgtotalerr
164}
165
166func (w *headerWriterWrite(ctx context.Contextmsg Message) (int64error) {
167    select {
168    case <-ctx.Done():
169        return 0ctx.Err()
170    default:
171    }
172    dataerr := EncodeMessage(msg)
173    if err != nil {
174        return 0fmt.Errorf("marshaling message: %v"err)
175    }
176    nerr := fmt.Fprintf(w.out"Content-Length: %v\r\n\r\n"len(data))
177    total := int64(n)
178    if err == nil {
179        nerr = w.out.Write(data)
180        total += int64(n)
181    }
182    return totalerr
183}
184
MembersX
rawReader.Read.r
rawWriter.Write
rawWriter.Write.msg
headerReader.in
headerReader.Read.BlockStmt.line
strconv
rawReader.Read.msg
headerFramer.Writer
rawWriter
rawWriter.out
rawWriter.Write.data
rawWriter.Write.err
headerWriter.out
strings
Writer
headerFramer
rawFramer.Writer
rawWriter.Write.ctx
HeaderFramer
headerReader.Read.msg
rawReader
headerReader.Read.total
headerWriter.Write.msg
rawReader.in
headerFramer.Reader.rw
headerReader.Read.r
headerReader.Read.ctx
rawFramer.Reader
rawReader.Read.ctx
rawWriter.Write.n
bufio
rawFramer.Reader.rw
headerReader.Read.length
headerReader.Read.n
headerWriter.Write.ctx
headerWriter.Write.err
rawFramer
rawReader.Read
headerReader.Read.err
headerWriter
headerFramer.Writer.rw
headerReader.Read.data
headerWriter.Write.w
Reader
headerReader.Read.BlockStmt.value
rawFramer.Writer.rw
rawReader.Read.raw
rawWriter.Write.w
headerFramer.Reader
headerReader.Read.BlockStmt.err
Framer
RawFramer
rawReader.Read.err
headerReader
headerReader.Read
headerWriter.Write
headerReader.Read.BlockStmt.colon
headerWriter.Write.data
headerWriter.Write.n
headerWriter.Write.total
Members
X