summaryrefslogtreecommitdiff
path: root/src/mongo/db/dbmessage.cpp
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2014-08-11 18:48:46 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2014-08-14 16:28:12 -0400
commit9105b69e1ded5b7d0d384d574103b0ee6bbb6122 (patch)
treea0d99a076a8017564ac271fe320310729b7577c3 /src/mongo/db/dbmessage.cpp
parentbd14042812b9bab796a83672f95b2d0e2e6b4252 (diff)
downloadmongo-9105b69e1ded5b7d0d384d574103b0ee6bbb6122.tar.gz
SERVER-14268: Backport from 2.6 to 2.4
Diffstat (limited to 'src/mongo/db/dbmessage.cpp')
-rw-r--r--src/mongo/db/dbmessage.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/mongo/db/dbmessage.cpp b/src/mongo/db/dbmessage.cpp
index 3f1e866291f..aebe88b1d07 100644
--- a/src/mongo/db/dbmessage.cpp
+++ b/src/mongo/db/dbmessage.cpp
@@ -52,6 +52,140 @@ 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;
+ }
+
+ long long DbMessage::getInt64(int offsetBytes) const {
+ verify(messageShouldHaveNs());
+ const char* p = _nsStart + _nsLen + 1;
+ checkReadOffset<long long>(p, offsetBytes);
+
+ return ((reinterpret_cast<const long long*>(p + offsetBytes)))[0];
+ }
+
+ 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::getFlags() const {
+ verify(messageShouldHaveNs());
+ const char* p = _nsStart + _nsLen + 1;
+ checkRead<int>(p, 1);
+
+ return ((reinterpret_cast<const int*>(p)))[0];
+ }
+
+ void DbMessage::setFlags(int value) {
+ verify(messageShouldHaveNs());
+ char* p = const_cast<char*>(_nsStart) + _nsLen + 1;
+ checkRead<int>(p, 1);
+
+ ((reinterpret_cast<int*>(p)))[0] = value;
+ }
+
+
+ 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 (cmdLine.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) {
+ 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>
+ void DbMessage::checkReadOffset(const char* start, size_t offset) const {
+ if ((_theEnd - start) < static_cast<int>(offset + sizeof(T))) {
+ uassert(18626, "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,