github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage/wiremessage.go (about) 1 // Copyright (C) MongoDB, Inc. 2022-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 8 9 import ( 10 "bytes" 11 "strings" 12 "sync/atomic" 13 14 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" 15 ) 16 17 // WireMessage represents a MongoDB wire message in binary form. 18 type WireMessage []byte 19 20 var globalRequestID int32 21 22 // CurrentRequestID returns the current request ID. 23 func CurrentRequestID() int32 { return atomic.LoadInt32(&globalRequestID) } 24 25 // NextRequestID returns the next request ID. 26 func NextRequestID() int32 { return atomic.AddInt32(&globalRequestID, 1) } 27 28 // OpCode represents a MongoDB wire protocol opcode. 29 type OpCode int32 30 31 // These constants are the valid opcodes for the version of the wireprotocol 32 // supported by this library. The skipped OpCodes are historical OpCodes that 33 // are no longer used. 34 const ( 35 OpReply OpCode = 1 36 _ OpCode = 1001 37 OpUpdate OpCode = 2001 38 OpInsert OpCode = 2002 39 _ OpCode = 2003 40 OpQuery OpCode = 2004 41 OpGetMore OpCode = 2005 42 OpDelete OpCode = 2006 43 OpKillCursors OpCode = 2007 44 OpCommand OpCode = 2010 45 OpCommandReply OpCode = 2011 46 OpCompressed OpCode = 2012 47 OpMsg OpCode = 2013 48 ) 49 50 // String implements the fmt.Stringer interface. 51 func (oc OpCode) String() string { 52 switch oc { 53 case OpReply: 54 return "OP_REPLY" 55 case OpUpdate: 56 return "OP_UPDATE" 57 case OpInsert: 58 return "OP_INSERT" 59 case OpQuery: 60 return "OP_QUERY" 61 case OpGetMore: 62 return "OP_GET_MORE" 63 case OpDelete: 64 return "OP_DELETE" 65 case OpKillCursors: 66 return "OP_KILL_CURSORS" 67 case OpCommand: 68 return "OP_COMMAND" 69 case OpCommandReply: 70 return "OP_COMMANDREPLY" 71 case OpCompressed: 72 return "OP_COMPRESSED" 73 case OpMsg: 74 return "OP_MSG" 75 default: 76 return "<invalid opcode>" 77 } 78 } 79 80 // QueryFlag represents the flags on an OP_QUERY message. 81 type QueryFlag int32 82 83 // These constants represent the individual flags on an OP_QUERY message. 84 const ( 85 _ QueryFlag = 1 << iota 86 TailableCursor 87 SecondaryOK 88 OplogReplay 89 NoCursorTimeout 90 AwaitData 91 Exhaust 92 Partial 93 ) 94 95 // String implements the fmt.Stringer interface. 96 func (qf QueryFlag) String() string { 97 strs := make([]string, 0) 98 if qf&TailableCursor == TailableCursor { 99 strs = append(strs, "TailableCursor") 100 } 101 if qf&SecondaryOK == SecondaryOK { 102 strs = append(strs, "SecondaryOK") 103 } 104 if qf&OplogReplay == OplogReplay { 105 strs = append(strs, "OplogReplay") 106 } 107 if qf&NoCursorTimeout == NoCursorTimeout { 108 strs = append(strs, "NoCursorTimeout") 109 } 110 if qf&AwaitData == AwaitData { 111 strs = append(strs, "AwaitData") 112 } 113 if qf&Exhaust == Exhaust { 114 strs = append(strs, "Exhaust") 115 } 116 if qf&Partial == Partial { 117 strs = append(strs, "Partial") 118 } 119 str := "[" 120 str += strings.Join(strs, ", ") 121 str += "]" 122 return str 123 } 124 125 // MsgFlag represents the flags on an OP_MSG message. 126 type MsgFlag uint32 127 128 // These constants represent the individual flags on an OP_MSG message. 129 const ( 130 ChecksumPresent MsgFlag = 1 << iota 131 MoreToCome 132 133 ExhaustAllowed MsgFlag = 1 << 16 134 ) 135 136 // ReplyFlag represents the flags of an OP_REPLY message. 137 type ReplyFlag int32 138 139 // These constants represent the individual flags of an OP_REPLY message. 140 const ( 141 CursorNotFound ReplyFlag = 1 << iota 142 QueryFailure 143 ShardConfigStale 144 AwaitCapable 145 ) 146 147 // String implements the fmt.Stringer interface. 148 func (rf ReplyFlag) String() string { 149 strs := make([]string, 0) 150 if rf&CursorNotFound == CursorNotFound { 151 strs = append(strs, "CursorNotFound") 152 } 153 if rf&QueryFailure == QueryFailure { 154 strs = append(strs, "QueryFailure") 155 } 156 if rf&ShardConfigStale == ShardConfigStale { 157 strs = append(strs, "ShardConfigStale") 158 } 159 if rf&AwaitCapable == AwaitCapable { 160 strs = append(strs, "AwaitCapable") 161 } 162 str := "[" 163 str += strings.Join(strs, ", ") 164 str += "]" 165 return str 166 } 167 168 // SectionType represents the type for 1 section in an OP_MSG 169 type SectionType uint8 170 171 // These constants represent the individual section types for a section in an OP_MSG 172 const ( 173 SingleDocument SectionType = iota 174 DocumentSequence 175 ) 176 177 // OpmsgWireVersion is the minimum wire version needed to use OP_MSG 178 const OpmsgWireVersion = 6 179 180 // CompressorID is the ID for each type of Compressor. 181 type CompressorID uint8 182 183 // These constants represent the individual compressor IDs for an OP_COMPRESSED. 184 const ( 185 CompressorNoOp CompressorID = iota 186 CompressorSnappy 187 CompressorZLib 188 CompressorZstd 189 ) 190 191 // String implements the fmt.Stringer interface. 192 func (id CompressorID) String() string { 193 switch id { 194 case CompressorNoOp: 195 return "CompressorNoOp" 196 case CompressorSnappy: 197 return "CompressorSnappy" 198 case CompressorZLib: 199 return "CompressorZLib" 200 case CompressorZstd: 201 return "CompressorZstd" 202 default: 203 return "CompressorInvalid" 204 } 205 } 206 207 const ( 208 // DefaultZlibLevel is the default level for zlib compression 209 DefaultZlibLevel = 6 210 // DefaultZstdLevel is the default level for zstd compression. 211 // Matches https://github.com/wiredtiger/wiredtiger/blob/f08bc4b18612ef95a39b12166abcccf207f91596/ext/compressors/zstd/zstd_compress.c#L299 212 DefaultZstdLevel = 6 213 ) 214 215 // AppendHeaderStart appends a header to the dst slice and returns an index where the wire message 216 // starts in dst and the updated slice. 217 func AppendHeaderStart(dst []byte, reqid, respto int32, opcode OpCode) (index int32, b []byte) { 218 index, dst = bsoncore.ReserveLength(dst) 219 dst = appendi32(dst, reqid) 220 dst = appendi32(dst, respto) 221 dst = appendi32(dst, int32(opcode)) 222 return index, dst 223 } 224 225 // AppendHeader appends a header to dst. 226 func AppendHeader(dst []byte, length, reqid, respto int32, opcode OpCode) []byte { 227 dst = appendi32(dst, length) 228 dst = appendi32(dst, reqid) 229 dst = appendi32(dst, respto) 230 dst = appendi32(dst, int32(opcode)) 231 return dst 232 } 233 234 // ReadHeader reads a wire message header from src. 235 func ReadHeader(src []byte) (length, requestID, responseTo int32, opcode OpCode, rem []byte, ok bool) { 236 if len(src) < 16 { 237 return 0, 0, 0, 0, src, false 238 } 239 length = (int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24) 240 requestID = (int32(src[4]) | int32(src[5])<<8 | int32(src[6])<<16 | int32(src[7])<<24) 241 responseTo = (int32(src[8]) | int32(src[9])<<8 | int32(src[10])<<16 | int32(src[11])<<24) 242 opcode = OpCode(int32(src[12]) | int32(src[13])<<8 | int32(src[14])<<16 | int32(src[15])<<24) 243 return length, requestID, responseTo, opcode, src[16:], true 244 } 245 246 // AppendQueryFlags appends the flags for an OP_QUERY wire message. 247 func AppendQueryFlags(dst []byte, flags QueryFlag) []byte { 248 return appendi32(dst, int32(flags)) 249 } 250 251 // AppendMsgFlags appends the flags for an OP_MSG wire message. 252 func AppendMsgFlags(dst []byte, flags MsgFlag) []byte { 253 return appendi32(dst, int32(flags)) 254 } 255 256 // AppendReplyFlags appends the flags for an OP_REPLY wire message. 257 func AppendReplyFlags(dst []byte, flags ReplyFlag) []byte { 258 return appendi32(dst, int32(flags)) 259 } 260 261 // AppendMsgSectionType appends the section type to dst. 262 func AppendMsgSectionType(dst []byte, stype SectionType) []byte { 263 return append(dst, byte(stype)) 264 } 265 266 // AppendQueryFullCollectionName appends the full collection name to dst. 267 func AppendQueryFullCollectionName(dst []byte, ns string) []byte { 268 return appendCString(dst, ns) 269 } 270 271 // AppendQueryNumberToSkip appends the number to skip to dst. 272 func AppendQueryNumberToSkip(dst []byte, skip int32) []byte { 273 return appendi32(dst, skip) 274 } 275 276 // AppendQueryNumberToReturn appends the number to return to dst. 277 func AppendQueryNumberToReturn(dst []byte, nor int32) []byte { 278 return appendi32(dst, nor) 279 } 280 281 // AppendReplyCursorID appends the cursor ID to dst. 282 func AppendReplyCursorID(dst []byte, id int64) []byte { 283 return appendi64(dst, id) 284 } 285 286 // AppendReplyStartingFrom appends the starting from field to dst. 287 func AppendReplyStartingFrom(dst []byte, sf int32) []byte { 288 return appendi32(dst, sf) 289 } 290 291 // AppendReplyNumberReturned appends the number returned to dst. 292 func AppendReplyNumberReturned(dst []byte, nr int32) []byte { 293 return appendi32(dst, nr) 294 } 295 296 // AppendCompressedOriginalOpCode appends the original opcode to dst. 297 func AppendCompressedOriginalOpCode(dst []byte, opcode OpCode) []byte { 298 return appendi32(dst, int32(opcode)) 299 } 300 301 // AppendCompressedUncompressedSize appends the uncompressed size of a 302 // compressed wiremessage to dst. 303 func AppendCompressedUncompressedSize(dst []byte, size int32) []byte { return appendi32(dst, size) } 304 305 // AppendCompressedCompressorID appends the ID of the compressor to dst. 306 func AppendCompressedCompressorID(dst []byte, id CompressorID) []byte { 307 return append(dst, byte(id)) 308 } 309 310 // AppendCompressedCompressedMessage appends the compressed wiremessage to dst. 311 func AppendCompressedCompressedMessage(dst []byte, msg []byte) []byte { return append(dst, msg...) } 312 313 // AppendGetMoreZero appends the zero field to dst. 314 func AppendGetMoreZero(dst []byte) []byte { 315 return appendi32(dst, 0) 316 } 317 318 // AppendGetMoreFullCollectionName appends the fullCollectionName field to dst. 319 func AppendGetMoreFullCollectionName(dst []byte, ns string) []byte { 320 return appendCString(dst, ns) 321 } 322 323 // AppendGetMoreNumberToReturn appends the numberToReturn field to dst. 324 func AppendGetMoreNumberToReturn(dst []byte, numToReturn int32) []byte { 325 return appendi32(dst, numToReturn) 326 } 327 328 // AppendGetMoreCursorID appends the cursorID field to dst. 329 func AppendGetMoreCursorID(dst []byte, cursorID int64) []byte { 330 return appendi64(dst, cursorID) 331 } 332 333 // AppendKillCursorsZero appends the zero field to dst. 334 func AppendKillCursorsZero(dst []byte) []byte { 335 return appendi32(dst, 0) 336 } 337 338 // AppendKillCursorsNumberIDs appends the numberOfCursorIDs field to dst. 339 func AppendKillCursorsNumberIDs(dst []byte, numIDs int32) []byte { 340 return appendi32(dst, numIDs) 341 } 342 343 // AppendKillCursorsCursorIDs appends each the cursorIDs field to dst. 344 func AppendKillCursorsCursorIDs(dst []byte, cursors []int64) []byte { 345 for _, cursor := range cursors { 346 dst = appendi64(dst, cursor) 347 } 348 return dst 349 } 350 351 // ReadMsgFlags reads the OP_MSG flags from src. 352 func ReadMsgFlags(src []byte) (flags MsgFlag, rem []byte, ok bool) { 353 i32, rem, ok := readi32(src) 354 return MsgFlag(i32), rem, ok 355 } 356 357 // IsMsgMoreToCome returns if the provided wire message is an OP_MSG with the more to come flag set. 358 func IsMsgMoreToCome(wm []byte) bool { 359 return len(wm) >= 20 && 360 OpCode(readi32unsafe(wm[12:16])) == OpMsg && 361 MsgFlag(readi32unsafe(wm[16:20]))&MoreToCome == MoreToCome 362 } 363 364 // ReadMsgSectionType reads the section type from src. 365 func ReadMsgSectionType(src []byte) (stype SectionType, rem []byte, ok bool) { 366 if len(src) < 1 { 367 return 0, src, false 368 } 369 return SectionType(src[0]), src[1:], true 370 } 371 372 // ReadMsgSectionSingleDocument reads a single document from src. 373 func ReadMsgSectionSingleDocument(src []byte) (doc bsoncore.Document, rem []byte, ok bool) { 374 return bsoncore.ReadDocument(src) 375 } 376 377 // ReadMsgSectionDocumentSequence reads an identifier and document sequence from src and returns the document sequence 378 // data parsed into a slice of BSON documents. 379 func ReadMsgSectionDocumentSequence(src []byte) (identifier string, docs []bsoncore.Document, rem []byte, ok bool) { 380 length, rem, ok := readi32(src) 381 if !ok || int(length) > len(src) { 382 return "", nil, rem, false 383 } 384 385 rem, ret := rem[:length-4], rem[length-4:] // reslice so we can just iterate a loop later 386 387 identifier, rem, ok = readcstring(rem) 388 if !ok { 389 return "", nil, rem, false 390 } 391 392 docs = make([]bsoncore.Document, 0) 393 var doc bsoncore.Document 394 for { 395 doc, rem, ok = bsoncore.ReadDocument(rem) 396 if !ok { 397 break 398 } 399 docs = append(docs, doc) 400 } 401 if len(rem) > 0 { 402 return "", nil, append(rem, ret...), false 403 } 404 405 return identifier, docs, ret, true 406 } 407 408 // ReadMsgSectionRawDocumentSequence reads an identifier and document sequence from src and returns the raw document 409 // sequence data. 410 func ReadMsgSectionRawDocumentSequence(src []byte) (identifier string, data []byte, rem []byte, ok bool) { 411 length, rem, ok := readi32(src) 412 if !ok || int(length) > len(src) { 413 return "", nil, rem, false 414 } 415 416 // After these assignments, rem will be the data containing the identifier string + the document sequence bytes and 417 // rest will be the rest of the wire message after this document sequence. 418 rem, rest := rem[:length-4], rem[length-4:] 419 420 identifier, rem, ok = readcstring(rem) 421 if !ok { 422 return "", nil, rem, false 423 } 424 425 return identifier, rem, rest, true 426 } 427 428 // ReadMsgChecksum reads a checksum from src. 429 func ReadMsgChecksum(src []byte) (checksum uint32, rem []byte, ok bool) { 430 i32, rem, ok := readi32(src) 431 return uint32(i32), rem, ok 432 } 433 434 // ReadQueryFlags reads OP_QUERY flags from src. 435 func ReadQueryFlags(src []byte) (flags QueryFlag, rem []byte, ok bool) { 436 i32, rem, ok := readi32(src) 437 return QueryFlag(i32), rem, ok 438 } 439 440 // ReadQueryFullCollectionName reads the full collection name from src. 441 func ReadQueryFullCollectionName(src []byte) (collname string, rem []byte, ok bool) { 442 return readcstring(src) 443 } 444 445 // ReadQueryNumberToSkip reads the number to skip from src. 446 func ReadQueryNumberToSkip(src []byte) (nts int32, rem []byte, ok bool) { 447 return readi32(src) 448 } 449 450 // ReadQueryNumberToReturn reads the number to return from src. 451 func ReadQueryNumberToReturn(src []byte) (ntr int32, rem []byte, ok bool) { 452 return readi32(src) 453 } 454 455 // ReadQueryQuery reads the query from src. 456 func ReadQueryQuery(src []byte) (query bsoncore.Document, rem []byte, ok bool) { 457 return bsoncore.ReadDocument(src) 458 } 459 460 // ReadQueryReturnFieldsSelector reads a return fields selector document from src. 461 func ReadQueryReturnFieldsSelector(src []byte) (rfs bsoncore.Document, rem []byte, ok bool) { 462 return bsoncore.ReadDocument(src) 463 } 464 465 // ReadReplyFlags reads OP_REPLY flags from src. 466 func ReadReplyFlags(src []byte) (flags ReplyFlag, rem []byte, ok bool) { 467 i32, rem, ok := readi32(src) 468 return ReplyFlag(i32), rem, ok 469 } 470 471 // ReadReplyCursorID reads a cursor ID from src. 472 func ReadReplyCursorID(src []byte) (cursorID int64, rem []byte, ok bool) { 473 return readi64(src) 474 } 475 476 // ReadReplyStartingFrom reads the starting from from src. 477 func ReadReplyStartingFrom(src []byte) (startingFrom int32, rem []byte, ok bool) { 478 return readi32(src) 479 } 480 481 // ReadReplyNumberReturned reads the numbered returned from src. 482 func ReadReplyNumberReturned(src []byte) (numberReturned int32, rem []byte, ok bool) { 483 return readi32(src) 484 } 485 486 // ReadReplyDocuments reads as many documents as possible from src 487 func ReadReplyDocuments(src []byte) (docs []bsoncore.Document, rem []byte, ok bool) { 488 rem = src 489 for { 490 var doc bsoncore.Document 491 doc, rem, ok = bsoncore.ReadDocument(rem) 492 if !ok { 493 break 494 } 495 496 docs = append(docs, doc) 497 } 498 499 return docs, rem, true 500 } 501 502 // ReadReplyDocument reads a reply document from src. 503 func ReadReplyDocument(src []byte) (doc bsoncore.Document, rem []byte, ok bool) { 504 return bsoncore.ReadDocument(src) 505 } 506 507 // ReadCompressedOriginalOpCode reads the original opcode from src. 508 func ReadCompressedOriginalOpCode(src []byte) (opcode OpCode, rem []byte, ok bool) { 509 i32, rem, ok := readi32(src) 510 return OpCode(i32), rem, ok 511 } 512 513 // ReadCompressedUncompressedSize reads the uncompressed size of a 514 // compressed wiremessage to dst. 515 func ReadCompressedUncompressedSize(src []byte) (size int32, rem []byte, ok bool) { 516 return readi32(src) 517 } 518 519 // ReadCompressedCompressorID reads the ID of the compressor to dst. 520 func ReadCompressedCompressorID(src []byte) (id CompressorID, rem []byte, ok bool) { 521 if len(src) < 1 { 522 return 0, src, false 523 } 524 return CompressorID(src[0]), src[1:], true 525 } 526 527 // ReadCompressedCompressedMessage reads the compressed wiremessage to dst. 528 func ReadCompressedCompressedMessage(src []byte, length int32) (msg []byte, rem []byte, ok bool) { 529 if len(src) < int(length) { 530 return nil, src, false 531 } 532 return src[:length], src[length:], true 533 } 534 535 // ReadKillCursorsZero reads the zero field from src. 536 func ReadKillCursorsZero(src []byte) (zero int32, rem []byte, ok bool) { 537 return readi32(src) 538 } 539 540 // ReadKillCursorsNumberIDs reads the numberOfCursorIDs field from src. 541 func ReadKillCursorsNumberIDs(src []byte) (numIDs int32, rem []byte, ok bool) { 542 return readi32(src) 543 } 544 545 // ReadKillCursorsCursorIDs reads numIDs cursor IDs from src. 546 func ReadKillCursorsCursorIDs(src []byte, numIDs int32) (cursorIDs []int64, rem []byte, ok bool) { 547 var i int32 548 var id int64 549 for i = 0; i < numIDs; i++ { 550 id, src, ok = readi64(src) 551 if !ok { 552 return cursorIDs, src, false 553 } 554 555 cursorIDs = append(cursorIDs, id) 556 } 557 return cursorIDs, src, true 558 } 559 560 func appendi32(dst []byte, i32 int32) []byte { 561 return append(dst, byte(i32), byte(i32>>8), byte(i32>>16), byte(i32>>24)) 562 } 563 564 func appendi64(b []byte, i int64) []byte { 565 return append(b, byte(i), byte(i>>8), byte(i>>16), byte(i>>24), byte(i>>32), byte(i>>40), byte(i>>48), byte(i>>56)) 566 } 567 568 func appendCString(b []byte, str string) []byte { 569 b = append(b, str...) 570 return append(b, 0x00) 571 } 572 573 func readi32(src []byte) (int32, []byte, bool) { 574 if len(src) < 4 { 575 return 0, src, false 576 } 577 578 return (int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24), src[4:], true 579 } 580 581 func readi32unsafe(src []byte) int32 { 582 return (int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24) 583 } 584 585 func readi64(src []byte) (int64, []byte, bool) { 586 if len(src) < 8 { 587 return 0, src, false 588 } 589 i64 := (int64(src[0]) | int64(src[1])<<8 | int64(src[2])<<16 | int64(src[3])<<24 | 590 int64(src[4])<<32 | int64(src[5])<<40 | int64(src[6])<<48 | int64(src[7])<<56) 591 return i64, src[8:], true 592 } 593 594 func readcstring(src []byte) (string, []byte, bool) { 595 idx := bytes.IndexByte(src, 0x00) 596 if idx < 0 { 597 return "", src, false 598 } 599 return string(src[:idx]), src[idx+1:], true 600 }