blob: c2cb153227c9ae4682e1ae113348b9923c1c29f1 [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7// Package wiremessage contains types for speaking the MongoDB Wire Protocol. Since this low
8// level library is meant to be used in the context of a driver and in the context of a server
9// all of the flags and types of the wire protocol are implemented. For each op there are two
10// corresponding implementations. One prefixed with Immutable which can be created by casting a
11// []byte to the type, and another prefixed with Mutable that is a struct with methods to mutate
12// the op.
13package wiremessage
14
15import (
16 "context"
17 "errors"
18 "fmt"
19 "io"
20 "sync/atomic"
21)
22
23// ErrInvalidMessageLength is returned when the provided message length is too small to be valid.
24var ErrInvalidMessageLength = errors.New("the message length is too small, it must be at least 16")
25
26// ErrUnknownOpCode is returned when the provided opcode is not a valid opcode.
27var ErrUnknownOpCode = errors.New("the opcode is unknown")
28
29var globalRequestID int32
30
31// CurrentRequestID returns the current request ID.
32func CurrentRequestID() int32 { return atomic.LoadInt32(&globalRequestID) }
33
34// NextRequestID returns the next request ID.
35func NextRequestID() int32 { return atomic.AddInt32(&globalRequestID, 1) }
36
37// Error represents an error related to wire protocol messages.
38type Error struct {
39 Type ErrorType
40 Message string
41}
42
43// Error implements the err interface.
44func (e Error) Error() string {
45 return e.Message
46}
47
48// ErrorType is the type of error, which indicates from which part of the code
49// the error originated.
50type ErrorType uint16
51
52// These constants are the types of errors exposed by this package.
53const (
54 ErrNil ErrorType = iota
55 ErrHeader
56 ErrOpQuery
57 ErrOpReply
58 ErrOpCompressed
59 ErrOpMsg
60 ErrRead
61)
62
63// OpCode represents a MongoDB wire protocol opcode.
64type OpCode int32
65
66// These constants are the valid opcodes for the version of the wireprotocol
67// supported by this library. The skipped OpCodes are historical OpCodes that
68// are no longer used.
69const (
70 OpReply OpCode = 1
71 _ OpCode = 1001
72 OpUpdate OpCode = 2001
73 OpInsert OpCode = 2002
74 _ OpCode = 2003
75 OpQuery OpCode = 2004
76 OpGetMore OpCode = 2005
77 OpDelete OpCode = 2006
78 OpKillCursors OpCode = 2007
79 OpCommand OpCode = 2010
80 OpCommandReply OpCode = 2011
81 OpCompressed OpCode = 2012
82 OpMsg OpCode = 2013
83)
84
85// String implements the fmt.Stringer interface.
86func (oc OpCode) String() string {
87 switch oc {
88 case OpReply:
89 return "OP_REPLY"
90 case OpUpdate:
91 return "OP_UPDATE"
92 case OpInsert:
93 return "OP_INSERT"
94 case OpQuery:
95 return "OP_QUERY"
96 case OpGetMore:
97 return "OP_GET_MORE"
98 case OpDelete:
99 return "OP_DELETE"
100 case OpKillCursors:
101 return "OP_KILL_CURSORS"
102 case OpCommand:
103 return "OP_COMMAND"
104 case OpCommandReply:
105 return "OP_COMMANDREPLY"
106 case OpCompressed:
107 return "OP_COMPRESSED"
108 case OpMsg:
109 return "OP_MSG"
110 default:
111 return "<invalid opcode>"
112 }
113}
114
115// WireMessage represents a message in the MongoDB wire protocol.
116type WireMessage interface {
117 Marshaler
118 Validator
119 Appender
120 fmt.Stringer
121
122 // Len returns the length in bytes of this WireMessage.
123 Len() int
124}
125
126// Validator is the interface implemented by types that can validate
127// themselves as a MongoDB wire protocol message.
128type Validator interface {
129 ValidateWireMessage() error
130}
131
132// Marshaler is the interface implemented by types that can marshal
133// themselves into a valid MongoDB wire protocol message.
134type Marshaler interface {
135 MarshalWireMessage() ([]byte, error)
136}
137
138// Appender is the interface implemented by types that can append themselves, as
139// a MongoDB wire protocol message, to the provided slice of bytes.
140type Appender interface {
141 AppendWireMessage([]byte) ([]byte, error)
142}
143
144// Unmarshaler is the interface implemented by types that can unmarshal a
145// MongoDB wire protocol message version of themselves. The input can be
146// assumed to be a valid MongoDB wire protocol message. UnmarshalWireMessage
147// must copy the data if it wishes to retain the data after returning.
148type Unmarshaler interface {
149 UnmarshalWireMessage([]byte) error
150}
151
152// Writer is the interface implemented by types that can have WireMessages
153// written to them.
154//
155// Implementation must obey the cancellation, timeouts, and deadlines of the
156// provided context.Context object.
157type Writer interface {
158 WriteWireMessage(context.Context, WireMessage) error
159}
160
161// Reader is the interface implemented by types that can have WireMessages
162// read from them.
163//
164// Implementation must obey the cancellation, timeouts, and deadlines of the
165// provided context.Context object.
166type Reader interface {
167 ReadWireMessage(context.Context) (WireMessage, error)
168}
169
170// ReadWriter is the interface implemented by types that can both read and write
171// WireMessages.
172type ReadWriter interface {
173 Reader
174 Writer
175}
176
177// ReadWriteCloser is the interface implemented by types that can read and write
178// WireMessages and can also be closed.
179type ReadWriteCloser interface {
180 Reader
181 Writer
182 io.Closer
183}
184
185// Transformer is the interface implemented by types that can alter a WireMessage.
186// Implementations should not directly alter the provided WireMessage and instead
187// make a copy of the message, alter it, and returned the new message.
188type Transformer interface {
189 TransformWireMessage(WireMessage) (WireMessage, error)
190}
191
192// ReadFrom will read a single WireMessage from the given io.Reader. This function will
193// validate the WireMessage. If the WireMessage is not valid, this method will
194// return both the error and the invalid WireMessage. If another type of processing
195// error occurs, WireMessage will be nil.
196//
197// This function will return the immutable versions of wire protocol messages. The
198// Convert function can be used to retrieve a mutable version of wire protocol
199// messages.
200func ReadFrom(io.Reader) (WireMessage, error) { return nil, nil }
201
202// Unmarshal will unmarshal data into a WireMessage.
203func Unmarshal([]byte) (WireMessage, error) { return nil, nil }
204
205// Validate will validate that data is a valid MongoDB wire protocol message.
206func Validate([]byte) error { return nil }