New upstream version 8.1.0
This commit is contained in:
259
client_module/source/common/net/message/NetMessage.h
Normal file
259
client_module/source/common/net/message/NetMessage.h
Normal file
@@ -0,0 +1,259 @@
|
||||
#ifndef NETMESSAGE_H_
|
||||
#define NETMESSAGE_H_
|
||||
|
||||
#include <common/net/sock/NetworkInterfaceCard.h>
|
||||
#include <common/net/sock/Socket.h>
|
||||
#include <common/toolkit/Serialization.h>
|
||||
#include <common/Common.h>
|
||||
#include "NetMessageTypes.h"
|
||||
|
||||
/**
|
||||
* Note: This "class" is not meant to be instantiated directly (consider it to be abstract).
|
||||
* It contains some "virtual" methods, as you can see in the struct NetMessage. Only the virtual
|
||||
* Method processIncoming(..) has a default implementation.
|
||||
* Derived classes have a destructor with a NetMessage-Pointer (instead of the real type)
|
||||
* because of the generic virtual destructor signature.
|
||||
* Derived classes normally have two constructors: One has no arguments and is used for
|
||||
* deserialization. The other one is the standard constructor.
|
||||
*/
|
||||
|
||||
// common message constants
|
||||
// ========================
|
||||
#define NETMSG_PREFIX ((0x42474653ULL << 32) + BEEGFS_DATA_VERSION)
|
||||
#define NETMSG_MIN_LENGTH NETMSG_HEADER_LENGTH
|
||||
#define NETMSG_HEADER_LENGTH 40 /* length of the header (see struct NetMessageHeader) */
|
||||
#define NETMSG_MAX_MSG_SIZE 65536 // 64kB
|
||||
#define NETMSG_MAX_PAYLOAD_SIZE ((unsigned)(NETMSG_MAX_MSG_SIZE - NETMSG_HEADER_LENGTH))
|
||||
|
||||
#define NETMSG_DEFAULT_USERID (~0) // non-zero to avoid mixing up with root userID
|
||||
|
||||
|
||||
// forward declaration
|
||||
struct App;
|
||||
|
||||
|
||||
struct NetMessageHeader;
|
||||
typedef struct NetMessageHeader NetMessageHeader;
|
||||
struct NetMessage;
|
||||
typedef struct NetMessage NetMessage;
|
||||
|
||||
struct NetMessageOps;
|
||||
|
||||
static inline void NETMESSAGE_FREE(NetMessage* this);
|
||||
|
||||
static inline void NetMessage_init(NetMessage* this, unsigned short msgType,
|
||||
const struct NetMessageOps* ops);
|
||||
|
||||
extern void __NetMessage_deserializeHeader(DeserializeCtx* ctx, struct NetMessageHeader* outHeader);
|
||||
extern void __NetMessage_serializeHeader(NetMessage* this, SerializeCtx* ctx, bool zeroLengthField);
|
||||
|
||||
extern void _NetMessage_serializeDummy(NetMessage* this, SerializeCtx* ctx);
|
||||
extern bool _NetMessage_deserializeDummy(NetMessage* this, DeserializeCtx* ctx);
|
||||
|
||||
|
||||
static inline unsigned NetMessage_extractMsgLengthFromBuf(const char* recvBuf);
|
||||
static inline bool NetMessage_serialize(NetMessage* this, char* buf, size_t bufLen);
|
||||
static inline bool NetMessage_checkHeaderFeatureFlagsCompat(NetMessage* this);
|
||||
|
||||
// virtual functions
|
||||
extern bool NetMessage_processIncoming(NetMessage* this, struct App* app,
|
||||
fhgfs_sockaddr_in* fromAddr, struct Socket* sock, char* respBuf, size_t bufLen);
|
||||
extern unsigned NetMessage_getSupportedHeaderFeatureFlagsMask(NetMessage* this);
|
||||
|
||||
// getters & setters
|
||||
static inline unsigned short NetMessage_getMsgType(NetMessage* this);
|
||||
static inline unsigned NetMessage_getMsgHeaderFeatureFlags(NetMessage* this);
|
||||
static inline bool NetMessage_isMsgHeaderFeatureFlagSet(NetMessage* this, unsigned flag);
|
||||
static inline void NetMessage_addMsgHeaderFeatureFlag(NetMessage* this, unsigned flag);
|
||||
static inline unsigned NetMessage_getMsgLength(NetMessage* this);
|
||||
static inline void NetMessage_setMsgHeaderUserID(NetMessage* this, unsigned userID);
|
||||
static inline void NetMessage_setMsgHeaderTargetID(NetMessage* this, uint16_t userID);
|
||||
|
||||
static inline void _NetMessage_setMsgType(NetMessage* this, unsigned short msgType);
|
||||
|
||||
|
||||
#define MSGHDRFLAG_BUDDYMIRROR_SECOND (0x01)
|
||||
#define MSGHDRFLAG_IS_SELECTIVE_ACK (0x02)
|
||||
#define MSGHDRFLAG_HAS_SEQUENCE_NO (0x04)
|
||||
|
||||
struct NetMessageHeader
|
||||
{
|
||||
unsigned msgLength; // in bytes
|
||||
uint16_t msgFeatureFlags; // feature flags for derived messages (depend on msgType)
|
||||
uint8_t msgCompatFeatureFlags; /* for derived messages, similar to msgFeatureFlags, but
|
||||
"compat" because there is no check whether receiver
|
||||
understands these flags, so they might be ignored. */
|
||||
uint8_t msgFlags;
|
||||
// char* msgPrefix; // NETMSG_PREFIX_STR (8 bytes)
|
||||
unsigned short msgType; // the type of payload, defined as NETMSGTYPE_x
|
||||
uint16_t msgTargetID; // targetID (not groupID) for per-target workers on storage server
|
||||
unsigned msgUserID; // system user ID for per-user msg queues, stats etc.
|
||||
uint64_t msgSequence; // for retries, 0 if not present
|
||||
uint64_t msgSequenceDone; // a sequence number that has been fully processed, or 0
|
||||
};
|
||||
|
||||
struct NetMessageOps
|
||||
{
|
||||
void (*serializePayload) (NetMessage* this, SerializeCtx* ctx);
|
||||
bool (*deserializePayload) (NetMessage* this, DeserializeCtx* ctx);
|
||||
|
||||
bool (*processIncoming) (NetMessage* this, struct App* app, fhgfs_sockaddr_in* fromAddr,
|
||||
struct Socket* sock, char* respBuf, size_t bufLen);
|
||||
unsigned (*getSupportedHeaderFeatureFlagsMask) (NetMessage* this);
|
||||
|
||||
void (*release)(NetMessage* this);
|
||||
|
||||
|
||||
// not strictly operations, but these are common to all messages and do not warrant their own
|
||||
// functions
|
||||
bool supportsSequenceNumbers;
|
||||
};
|
||||
|
||||
struct NetMessage
|
||||
{
|
||||
struct NetMessageHeader msgHeader;
|
||||
|
||||
const struct NetMessageOps* ops;
|
||||
};
|
||||
|
||||
|
||||
void NetMessage_init(NetMessage* this, unsigned short msgType, const struct NetMessageOps* ops)
|
||||
{
|
||||
memset(this, 0, sizeof(*this) ); // clear function pointers etc.
|
||||
|
||||
// this->msgLength = 0; // zero'ed by memset
|
||||
// this->msgFeatureFlags = 0; // zero'ed by memset
|
||||
|
||||
this->msgHeader.msgType = msgType;
|
||||
|
||||
// needs to be set to actual ID by some async flushers etc
|
||||
this->msgHeader.msgUserID = FhgfsCommon_getCurrentUserID();
|
||||
|
||||
// this->msgTargetID = 0; // zero'ed by memset
|
||||
|
||||
this->ops = ops;
|
||||
}
|
||||
|
||||
#define NETMESSAGE_CONSTRUCT(TYPE) \
|
||||
({ \
|
||||
TYPE* msg = os_kmalloc(sizeof(TYPE)); \
|
||||
TYPE##_init(msg); \
|
||||
(NetMessage*)msg; \
|
||||
})
|
||||
|
||||
static inline void NETMESSAGE_FREE(NetMessage* msg)
|
||||
{
|
||||
if (msg->ops->release)
|
||||
msg->ops->release(msg);
|
||||
|
||||
kfree(msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* recvBuf must be at least NETMSG_MIN_LENGTH long
|
||||
*/
|
||||
unsigned NetMessage_extractMsgLengthFromBuf(const char* recvBuf)
|
||||
{
|
||||
unsigned msgLength;
|
||||
DeserializeCtx ctx = { recvBuf, sizeof(msgLength) };
|
||||
|
||||
Serialization_deserializeUInt(&ctx, &msgLength);
|
||||
|
||||
return msgLength;
|
||||
}
|
||||
|
||||
bool NetMessage_serialize(NetMessage* this, char* buf, size_t bufLen)
|
||||
{
|
||||
SerializeCtx ctx = {
|
||||
.data = buf,
|
||||
};
|
||||
|
||||
if(unlikely(bufLen < NetMessage_getMsgLength(this) ) )
|
||||
return false;
|
||||
|
||||
__NetMessage_serializeHeader(this, &ctx, false);
|
||||
this->ops->serializePayload(this, &ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the msg sender has set an incompatible feature flag.
|
||||
*
|
||||
* @return false if an incompatible feature flag was set
|
||||
*/
|
||||
bool NetMessage_checkHeaderFeatureFlagsCompat(NetMessage* this)
|
||||
{
|
||||
unsigned unsupportedFlags = ~(this->ops->getSupportedHeaderFeatureFlagsMask(this) );
|
||||
if(unlikely(this->msgHeader.msgFeatureFlags & unsupportedFlags) )
|
||||
return false; // an unsupported flag was set
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned short NetMessage_getMsgType(NetMessage* this)
|
||||
{
|
||||
return this->msgHeader.msgType;
|
||||
}
|
||||
|
||||
unsigned NetMessage_getMsgHeaderFeatureFlags(NetMessage* this)
|
||||
{
|
||||
return this->msgHeader.msgFeatureFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test flag. (For convenience and readability.)
|
||||
*
|
||||
* @return true if given flag is set.
|
||||
*/
|
||||
bool NetMessage_isMsgHeaderFeatureFlagSet(NetMessage* this, unsigned flag)
|
||||
{
|
||||
return (this->msgHeader.msgFeatureFlags & flag) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add another flag without clearing the previously set flags.
|
||||
*
|
||||
* Note: The receiver will reject this message if it doesn't know the given feature flag.
|
||||
*/
|
||||
void NetMessage_addMsgHeaderFeatureFlag(NetMessage* this, unsigned flag)
|
||||
{
|
||||
this->msgHeader.msgFeatureFlags |= flag;
|
||||
}
|
||||
|
||||
unsigned NetMessage_getMsgLength(NetMessage* this)
|
||||
{
|
||||
if(!this->msgHeader.msgLength)
|
||||
{
|
||||
SerializeCtx ctx = { NULL, 0 };
|
||||
|
||||
__NetMessage_serializeHeader(this, &ctx, true);
|
||||
this->ops->serializePayload(this, &ctx);
|
||||
|
||||
this->msgHeader.msgLength = ctx.length;
|
||||
}
|
||||
|
||||
return this->msgHeader.msgLength;
|
||||
}
|
||||
|
||||
void NetMessage_setMsgHeaderUserID(NetMessage* this, unsigned userID)
|
||||
{
|
||||
this->msgHeader.msgUserID = userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param targetID this has to be an actual targetID (not a groupID).
|
||||
*/
|
||||
void NetMessage_setMsgHeaderTargetID(NetMessage* this, uint16_t targetID)
|
||||
{
|
||||
this->msgHeader.msgTargetID = targetID;
|
||||
}
|
||||
|
||||
void _NetMessage_setMsgType(NetMessage* this, unsigned short msgType)
|
||||
{
|
||||
this->msgHeader.msgType = msgType;
|
||||
}
|
||||
|
||||
|
||||
#endif /*NETMESSAGE_H_*/
|
||||
Reference in New Issue
Block a user