summaryrefslogtreecommitdiff
path: root/src/mongo/db/dbmessage.cpp
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2014-07-30 10:45:36 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2014-07-30 10:46:16 -0400
commitdac9ac4a46348a67296b8b3ff11c58e522bd1b0b (patch)
treee91a666d945295c4789376c027742b8e9976ac05 /src/mongo/db/dbmessage.cpp
parent6d66597265e158ec16dd31f823f0d474194519e7 (diff)
downloadmongo-dac9ac4a46348a67296b8b3ff11c58e522bd1b0b.tar.gz
SERVER-14268: Improve server message parsing
Diffstat (limited to 'src/mongo/db/dbmessage.cpp')
-rw-r--r--src/mongo/db/dbmessage.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/mongo/db/dbmessage.cpp b/src/mongo/db/dbmessage.cpp
index 4e951cc5e78..a3b06058547 100644
--- a/src/mongo/db/dbmessage.cpp
+++ b/src/mongo/db/dbmessage.cpp
@@ -65,6 +65,107 @@ namespace mongo {
return ss.str();
}
+ DbMessage::DbMessage(const Message& msg) : _msg(msg), _nsStart(NULL), _mark(NULL), _nsLen(0) {
+ // for received messages, Message has only one buffer
+ _theEnd = _msg.singleData()->_data + _msg.singleData()->dataLen();
+ _nextjsobj = _msg.singleData()->_data;
+
+ _reserved = readAndAdvance<int>();
+
+ // Read packet for NS
+ if (messageShouldHaveNs()) {
+
+ // Limit = buffer size of message -
+ // (first int4 in message which is either flags or a zero constant)
+ size_t limit = _msg.singleData()->dataLen() - sizeof(int);
+
+ _nsStart = _nextjsobj;
+ _nsLen = strnlen(_nsStart, limit);
+
+ // Validate there is room for a null byte in the buffer
+ // Strings can be zero length
+ uassert(18633, "Failed to parse ns string", _nsLen <= (limit - 1));
+
+ _nextjsobj += _nsLen + 1; // skip namespace + null
+ }
+ }
+
+ const char * DbMessage::getns() const {
+ verify(messageShouldHaveNs());
+ return _nsStart;
+ }
+
+ int DbMessage::getQueryNToReturn() const {
+ verify(messageShouldHaveNs());
+ const char* p = _nsStart + _nsLen + 1;
+ checkRead<int>(p, 2);
+
+ return ((reinterpret_cast<const int*>(p)))[1];
+ }
+
+ int DbMessage::pullInt() {
+ return readAndAdvance<int>();
+ }
+
+ long long DbMessage::pullInt64() {
+ return readAndAdvance<long long>();
+ }
+
+ const long long* DbMessage::getArray(size_t count) const {
+ checkRead<long long>(_nextjsobj, count);
+ return reinterpret_cast<const long long*>(_nextjsobj);
+ }
+
+ BSONObj DbMessage::nextJsObj() {
+ massert(10304,
+ "Client Error: Remaining data too small for BSON object",
+ _nextjsobj != NULL && _theEnd - _nextjsobj >= 5);
+
+ if (serverGlobalParams.objcheck) {
+ Status status = validateBSON(_nextjsobj, _theEnd - _nextjsobj);
+ massert(10307,
+ str::stream() << "Client Error: bad object in message: " << status.reason(),
+ status.isOK());
+ }
+
+ BSONObj js(_nextjsobj);
+ verify(js.objsize() >= 5);
+ verify(js.objsize() <= (_theEnd - _nextjsobj));
+
+ _nextjsobj += js.objsize();
+ if (_nextjsobj >= _theEnd)
+ _nextjsobj = NULL;
+ return js;
+ }
+
+ void DbMessage::markReset(const char * toMark = NULL) {
+ if (toMark == NULL) {
+ toMark = _mark;
+ }
+
+ verify(toMark);
+ _nextjsobj = toMark;
+ }
+
+ template<typename T>
+ void DbMessage::checkRead(const char* start, size_t count) const {
+ if ((_theEnd - start) < static_cast<int>(sizeof(T) * count)) {
+ uassert(18634, "Not enough data to read", false);
+ }
+ }
+
+ template<typename T>
+ T DbMessage::read() const {
+ checkRead<T>(_nextjsobj, 1);
+
+ return *(reinterpret_cast<const T*>(_nextjsobj));
+ }
+
+ template<typename T> T DbMessage::readAndAdvance() {
+ T t = read<T>();
+ _nextjsobj += sizeof(T);
+ return t;
+ }
void replyToQuery(int queryResultFlags,
AbstractMessagingPort* p, Message& requestMsg,