@@ -53,6 +53,107 @@ namespace mongo {
5353 return ss.str ();
5454 }
5555
56+ DbMessage::DbMessage (const Message& msg) : _msg(msg), _nsStart(NULL ), _mark(NULL ), _nsLen(0 ) {
57+ // for received messages, Message has only one buffer
58+ _theEnd = _msg.singleData ()->_data + _msg.singleData ()->dataLen ();
59+ _nextjsobj = _msg.singleData ()->_data ;
60+
61+ _reserved = readAndAdvance<int >();
62+
63+ // Read packet for NS
64+ if (messageShouldHaveNs ()) {
65+
66+ // Limit = buffer size of message -
67+ // (first int4 in message which is either flags or a zero constant)
68+ size_t limit = _msg.singleData ()->dataLen () - sizeof (int );
69+
70+ _nsStart = _nextjsobj;
71+ _nsLen = strnlen (_nsStart, limit);
72+
73+ // Validate there is room for a null byte in the buffer
74+ // Strings can be zero length
75+ uassert (18633 , " Failed to parse ns string" , _nsLen <= (limit - 1 ));
76+
77+ _nextjsobj += _nsLen + 1 ; // skip namespace + null
78+ }
79+ }
80+
81+ const char * DbMessage::getns () const {
82+ verify (messageShouldHaveNs ());
83+ return _nsStart;
84+ }
85+
86+ int DbMessage::getQueryNToReturn () const {
87+ verify (messageShouldHaveNs ());
88+ const char * p = _nsStart + _nsLen + 1 ;
89+ checkRead<int >(p, 2 );
90+
91+ return ((reinterpret_cast <const int *>(p)))[1 ];
92+ }
93+
94+ int DbMessage::pullInt () {
95+ return readAndAdvance<int >();
96+ }
97+
98+ long long DbMessage::pullInt64 () {
99+ return readAndAdvance<long long >();
100+ }
101+
102+ const long long * DbMessage::getArray (size_t count) const {
103+ checkRead<long long >(_nextjsobj, count);
104+ return reinterpret_cast <const long long *>(_nextjsobj);
105+ }
106+
107+ BSONObj DbMessage::nextJsObj () {
108+ massert (10304 ,
109+ " Client Error: Remaining data too small for BSON object" ,
110+ _nextjsobj != NULL && _theEnd - _nextjsobj >= 5 );
111+
112+ if (serverGlobalParams.objcheck ) {
113+ Status status = validateBSON (_nextjsobj, _theEnd - _nextjsobj);
114+ massert (10307 ,
115+ str::stream () << " Client Error: bad object in message: " << status.reason (),
116+ status.isOK ());
117+ }
118+
119+ BSONObj js (_nextjsobj);
120+ verify (js.objsize () >= 5 );
121+ verify (js.objsize () <= (_theEnd - _nextjsobj));
122+
123+ _nextjsobj += js.objsize ();
124+ if (_nextjsobj >= _theEnd)
125+ _nextjsobj = NULL ;
126+ return js;
127+ }
128+
129+ void DbMessage::markReset (const char * toMark = NULL ) {
130+ if (toMark == NULL ) {
131+ toMark = _mark;
132+ }
133+
134+ verify (toMark);
135+ _nextjsobj = toMark;
136+ }
137+
138+ template <typename T>
139+ void DbMessage::checkRead (const char * start, size_t count) const {
140+ if ((_theEnd - start) < static_cast <int >(sizeof (T) * count)) {
141+ uassert (18634 , " Not enough data to read" , false );
142+ }
143+ }
144+
145+ template <typename T>
146+ T DbMessage::read () const {
147+ checkRead<T>(_nextjsobj, 1 );
148+
149+ return *(reinterpret_cast <const T*>(_nextjsobj));
150+ }
151+
152+ template <typename T> T DbMessage::readAndAdvance () {
153+ T t = read<T>();
154+ _nextjsobj += sizeof (T);
155+ return t;
156+ }
56157
57158 void replyToQuery (int queryResultFlags,
58159 AbstractMessagingPort* p, Message& requestMsg,
0 commit comments