0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 00:56:44 +01:00
mongodb/util/message.h

203 lines
5.5 KiB
C
Raw Normal View History

2008-06-06 15:43:15 +02:00
// message.h
/**
* Copyright (C) 2008 10gen Inc.
2008-12-29 02:28:49 +01:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
2008-12-29 02:28:49 +01:00
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
2008-12-29 02:28:49 +01:00
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2008-06-06 15:43:15 +02:00
#pragma once
#include "../util/sock.h"
2009-01-14 23:09:51 +01:00
namespace mongo {
class Message;
class MessagingPort;
class PiggyBackData;
typedef WrappingInt MSGID;
class Listener {
public:
Listener(const string &_ip, int p) : ip(_ip), port(p) { }
2009-02-18 19:42:32 +01:00
virtual ~Listener() {}
2009-04-01 18:26:31 +02:00
bool init(); // set up socket
int socket() const { return sock; }
void listen(); // never returns (start a thread)
/* spawn a thread, etc., then return */
virtual void accepted(MessagingPort *mp) = 0;
private:
string ip;
int port;
2009-04-01 18:26:31 +02:00
int sock;
};
2008-06-06 15:43:15 +02:00
class AbstractMessagingPort {
public:
virtual ~AbstractMessagingPort() { }
virtual void reply(Message& received, Message& response, MSGID responseTo) = 0; // like the reply below, but doesn't rely on received.data still being available
virtual void reply(Message& received, Message& response) = 0;
};
2008-06-06 15:43:15 +02:00
class MessagingPort : public AbstractMessagingPort {
public:
MessagingPort(int sock, SockAddr& farEnd);
MessagingPort();
~MessagingPort();
2008-06-06 15:43:15 +02:00
void shutdown();
2008-08-13 18:17:18 +02:00
bool connect(SockAddr& farEnd);
2008-06-06 15:43:15 +02:00
/* it's assumed if you reuse a message object, that it doesn't cross MessagingPort's.
also, the Message data will go out of scope on the subsequent recv call.
*/
bool recv(Message& m);
void reply(Message& received, Message& response, MSGID responseTo);
void reply(Message& received, Message& response);
bool call(Message& toSend, Message& response);
void say(Message& toSend, int responseTo = -1);
2008-06-06 15:43:15 +02:00
void piggyBack( Message& toSend , int responseTo = -1 );
private:
int sock;
PiggyBackData * piggyBackData;
public:
SockAddr farEnd;
friend class PiggyBackData;
2008-12-29 02:28:49 +01:00
};
2009-02-02 04:26:26 +01:00
//#pragma pack()
#pragma pack(1)
2008-12-29 02:28:49 +01:00
enum Operations {
opReply = 1, /* reply. responseTo is set. */
dbMsg = 1000, /* generic msg command followed by a string */
dbUpdate = 2001, /* update object */
dbInsert = 2002,
//dbGetByOID = 2003,
dbQuery = 2004,
dbGetMore = 2005,
dbDelete = 2006,
dbKillCursors = 2007
};
2008-12-29 02:28:49 +01:00
2009-03-17 22:24:38 +01:00
bool doesOpGetAResponse( int op );
struct MsgData {
int len; /* len of the msg, including this field */
MSGID id; /* request/reply id's match... */
MSGID responseTo; /* id of the message we are responding to */
int _operation;
int operation() const {
return _operation;
}
void setOperation(int o) {
_operation = o;
}
char _data[4];
int& dataAsInt() {
return *((int *) _data);
}
bool valid(){
if ( len <= 0 || len > ( 1024 * 1024 * 10 ) )
return false;
if ( _operation < 0 || _operation > 100000 )
return false;
return true;
}
int dataLen(); // len without header
};
const int MsgDataHeaderSize = sizeof(MsgData) - 4;
inline int MsgData::dataLen() {
return len - MsgDataHeaderSize;
2008-12-29 02:28:49 +01:00
}
2008-06-06 15:43:15 +02:00
#pragma pack()
2009-01-09 23:06:14 +01:00
class Message {
public:
Message() {
data = 0;
freeIt = false;
}
Message( void * _data , bool _freeIt ) {
data = (MsgData*)_data;
freeIt = _freeIt;
};
~Message() {
reset();
}
SockAddr from;
MsgData *data;
Message& operator=(Message& r) {
assert( data == 0 );
data = r.data;
assert( r.freeIt );
r.freeIt = false;
r.data = 0;
freeIt = true;
return *this;
}
void reset() {
if ( freeIt && data )
free(data);
data = 0;
freeIt = false;
}
void setData(MsgData *d, bool _freeIt) {
assert( data == 0 );
freeIt = _freeIt;
data = d;
}
void setData(int operation, const char *msgtxt) {
setData(operation, msgtxt, strlen(msgtxt)+1);
}
void setData(int operation, const char *msgdata, int len) {
assert(data == 0);
int dataLen = len + sizeof(MsgData) - 4;
MsgData *d = (MsgData *) malloc(dataLen);
memcpy(d->_data, msgdata, len);
d->len = fixEndian(dataLen);
d->setOperation(operation);
freeIt= true;
data = d;
}
bool doIFreeIt() {
return freeIt;
}
private:
bool freeIt;
};
2009-01-14 23:09:51 +01:00
2009-02-06 22:21:49 +01:00
class SocketException : public DBException {
public:
virtual const char* what() const throw() { return "socket exception"; }
2009-02-03 22:48:12 +01:00
};
MSGID nextMessageId();
2009-01-14 23:09:51 +01:00
} // namespace mongo