00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "aiomsg/msg_cpp.h"
00029 #include "base/date.h"
00030
00031 #include "base/string.hpp"
00032 #include "base/memory.hpp"
00033 #include "base/except.h"
00034 #include "base/list.hpp"
00035 #include "base/common.hpp"
00036 #include "base/number.hpp"
00037
00038 #include "xml/xmlimpl.h"
00039 #include "crypt/crypt.hpp"
00040 #include "crypt/base64.h"
00041
00042 BEGIN_TERIMBER_NAMESPACE
00043 #pragma pack(4)
00044
00045 extern exception_table msgMsgTable;
00046
00047 msg_cpp::msg_cpp(byte_allocator* allocator_, size_t size_) :
00048 _type(user_type_send),
00049 _marker(null_uuid),
00050 _timestamp(date()),
00051 _allocator(allocator_),
00052 _sender(null_uuid),
00053 _receiver(null_uuid),
00054 _sessionid(null_uuid),
00055 _size(0),
00056 _body(0),
00057 _block(0)
00058 {
00059 assert(_allocator);
00060 msgid = MSG_EMPTY_ID;
00061 majver = 0;
00062 minver = 0;
00063 timeout = msg_default_timeout;
00064 priority = MSG_PRIORITY_NORMAL;
00065 resize(size_);
00066 }
00067
00068
00069 msg_cpp::~msg_cpp()
00070 {
00071 }
00072
00073 void
00074 msg_cpp::pack_msg(const room_byte_t* key)
00075 {
00076 ub1_t* pt = (ub1_t*)_block + sizeof(ub4_t);
00077
00078
00079
00080
00081
00082 pack32(pt, msgid);
00083 pack32(pt, majver);
00084 pack32(pt, minver);
00085 pack32(pt, priority);
00086 pack64(pt, timeout);
00087
00088
00089
00090 pack32(pt, _type);
00091
00092 packaddr(pt, _marker);
00093 packaddr(pt, _sender);
00094 packaddr(pt, _receiver);
00095 packaddr(pt, _sessionid);
00096 pack64(pt, _timestamp);
00097 pack32(pt, _size);
00098
00099
00100 if (_size && key)
00101 {
00102 crypt ch(*key, key->size(), MD5);
00103 size_t ch_size = (size_t)_size;
00104 ch.encode((ub1_t*)_body, ch_size, RIJNDAEL);
00105 }
00106 }
00107
00108 void
00109 msg_cpp::unpack_msg(const room_byte_t* key)
00110 {
00111 const ub1_t* pt = (const ub1_t*)_block;
00112
00113 ub4_t size = 0;
00114 unpack32(pt, size);
00115
00116 if (size < block_size(0))
00117 exception::_throw(MSG_RESULT_INVALID_MSGFORMAT, &msgMsgTable);
00118
00119 try
00120 {
00121
00122 unpack32(pt, msgid);
00123 unpack32(pt, majver);
00124 unpack32(pt, minver);
00125 unpack32(pt, priority);
00126 unpack64(pt, timeout);
00127
00128
00129
00130 unpack32(pt, (ub4_t&)_type);
00131
00132 unpackaddr(pt, _marker);
00133 unpackaddr(pt, _sender);
00134 unpackaddr(pt, _receiver);
00135 unpackaddr(pt, _sessionid);
00136 unpack64(pt, (ub8_t&)_timestamp);
00137 unpack32(pt, _size);
00138
00139 if (size != block_size(_size))
00140 exception::_throw(MSG_RESULT_INVALID_MSGFORMAT, &msgMsgTable);
00141
00142 if (_size)
00143 {
00144 _body = (ub1_t*)_block + _block_body_offset();
00145 if (key)
00146 {
00147 crypt ch(*key, key->size(), MD5);
00148 size_t ch_size = (size_t)crypt_size(_size);
00149 ch.decode((ub1_t*)_body, ch_size, RIJNDAEL);
00150 }
00151 }
00152 else
00153 _body = 0;
00154
00155 }
00156 catch (exception& x)
00157 {
00158 throw x;
00159 }
00160 catch (...)
00161 {
00162 exception::_throw(MSG_RESULT_INVALID_MSGFORMAT, &msgMsgTable);
00163 }
00164 }
00165
00166
00167 bool
00168 msg_cpp::resize(size_t size_)
00169 {
00170 ub1_t* buf = 0;
00171
00172 if (!_block)
00173 {
00174 buf = (ub1_t*)_allocator->allocate((size_t)block_size(size_));
00175 if (!buf)
00176 return false;
00177
00178
00179 _block = buf;
00180 }
00181 else if (_size < size_)
00182 {
00183
00184 buf = (ub1_t*)_allocator->allocate((size_t)block_size(size_));
00185 if (!buf)
00186 return false;
00187
00188
00189
00190
00191 if (_size)
00192 {
00193 assert(_body && _block);
00194 memcpy(buf + _block_body_offset(), _body, (size_t)_size);
00195 }
00196
00197 _block = buf;
00198 }
00199 else if (_size > size_)
00200 {
00201 buf = (ub1_t*)_block;
00202 memset(buf + _block_body_offset() + size_, 0, _size - size_);
00203 _size = (ub4_t)size_;
00204 }
00205 else
00206 return true;
00207
00208
00209 _size = (ub4_t)size_;
00210
00211
00212 if (_size)
00213 _body = buf + _block_body_offset();
00214 else
00215 _body = 0;
00216
00217
00218 pack32(buf, (ub4_t)block_size(_size));
00219
00220 return true;
00221 }
00222
00224
00225 void
00226 msg_pack::make_reply_msg(const msg_cpp* msg_, msg_cpp* reply_)
00227 {
00228 reply_->_receiver = msg_->_sender;
00229 reply_->_sender = msg_->_receiver;
00230
00231
00232 reply_->_marker = msg_->_marker;
00233 switch (msg_->_type)
00234 {
00235 case user_type_send:
00236 reply_->_type = user_type_reply;
00237 break;
00238 case user_type_send_async:
00239 reply_->_type = user_type_reply_async;
00240 break;
00241 case handshake_type:
00242 reply_->_type = handshake_type;
00243 break;
00244 case system_type:
00245 reply_->_type = system_type;
00246 break;
00247 default:
00248 assert(false);
00249 }
00250 }
00251
00252
00253 void
00254 msg_pack::make_error_msg(msg_cpp* msg_, const char* text_)
00255 {
00256 msg_->msgid = MSG_ERROR_ID;
00257 const char* err_text = text_ ? text_ : "unknown error";
00258 size_t len = strlen(err_text);
00259 msg_->resize(len + 1);
00260 memcpy(msg_->get_body(), err_text, len + 1);
00261 }
00262
00263 #pragma pack()
00264 END_TERIMBER_NAMESPACE