...
1 package pgproto3
2
3 import (
4 "encoding/hex"
5 "errors"
6 "fmt"
7
8 "github.com/jackc/pgx/v5/internal/pgio"
9 )
10
11
12
13 const maxMessageBodyLen = (0x3fffffff - 1)
14
15
16
17 type Message interface {
18
19
20 Decode(data []byte) error
21
22
23 Encode(dst []byte) ([]byte, error)
24 }
25
26
27 type FrontendMessage interface {
28 Message
29 Frontend()
30 }
31
32
33 type BackendMessage interface {
34 Message
35 Backend()
36 }
37
38 type AuthenticationResponseMessage interface {
39 BackendMessage
40 AuthenticationResponse()
41 }
42
43 type invalidMessageLenErr struct {
44 messageType string
45 expectedLen int
46 actualLen int
47 }
48
49 func (e *invalidMessageLenErr) Error() string {
50 return fmt.Sprintf("%s body must have length of %d, but it is %d", e.messageType, e.expectedLen, e.actualLen)
51 }
52
53 type invalidMessageFormatErr struct {
54 messageType string
55 details string
56 }
57
58 func (e *invalidMessageFormatErr) Error() string {
59 return fmt.Sprintf("%s body is invalid %s", e.messageType, e.details)
60 }
61
62 type writeError struct {
63 err error
64 safeToRetry bool
65 }
66
67 func (e *writeError) Error() string {
68 return fmt.Sprintf("write failed: %s", e.err.Error())
69 }
70
71 func (e *writeError) SafeToRetry() bool {
72 return e.safeToRetry
73 }
74
75 func (e *writeError) Unwrap() error {
76 return e.err
77 }
78
79 type ExceededMaxBodyLenErr struct {
80 MaxExpectedBodyLen int
81 ActualBodyLen int
82 }
83
84 func (e *ExceededMaxBodyLenErr) Error() string {
85 return fmt.Sprintf("invalid body length: expected at most %d, but got %d", e.MaxExpectedBodyLen, e.ActualBodyLen)
86 }
87
88
89 func getValueFromJSON(v map[string]string) ([]byte, error) {
90 if v == nil {
91 return nil, nil
92 }
93 if text, ok := v["text"]; ok {
94 return []byte(text), nil
95 }
96 if binary, ok := v["binary"]; ok {
97 return hex.DecodeString(binary)
98 }
99 return nil, errors.New("unknown protocol representation")
100 }
101
102
103
104 func beginMessage(dst []byte, t byte) ([]byte, int) {
105 dst = append(dst, t)
106 sp := len(dst)
107 dst = pgio.AppendInt32(dst, -1)
108 return dst, sp
109 }
110
111
112
113 func finishMessage(dst []byte, sp int) ([]byte, error) {
114 messageBodyLen := len(dst[sp:])
115 if messageBodyLen > maxMessageBodyLen {
116 return nil, errors.New("message body too large")
117 }
118 pgio.SetInt32(dst[sp:], int32(messageBodyLen))
119 return dst, nil
120 }
121
View as plain text