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
00034 #include <netinet/in.h>
00035 #include <string.h>
00036 #include <cctype>
00037 #include <fstream>
00038 #include <ostream>
00039 #include <sstream>
00040 #include <iomanip>
00041
00042 #include "network_message.h"
00043
00044 #include "logfile.h"
00045
00046 namespace protlib {
00047
00048
00049 using namespace protlib::log;
00055 NetMsgError::NetMsgError(error_t e) : err(e) {}
00056
00057 const char* NetMsgError::getstr() const { return errstr[err]; }
00058
00060 const char* const NetMsgError::errstr[] =
00061 {
00062 "Network message too long.",
00063 "Not enough memory to allocate network message.",
00064 "Operation not valid because of pointer position in NetMsg buffer.",
00065 "NULL pointer argument in call to NetMsg constructor.",
00066 "Invalid start offset.",
00067 "NetMsg buffer too short.",
00068 "Invalid buffer size: zero"
00069 };
00070
00074 const uint32 NetMsg::max_size = 128000;
00075
00079 NetMsg::NetMsg(uint32 s) {
00080 if (s>max_size) throw NetMsgError(NetMsgError::ERROR_TOO_LONG);
00081 if (s==0) throw NetMsgError(NetMsgError::ERROR_INVALID_BUFSIZE);
00082 buf = new(nothrow) uchar[s];
00083 if (!buf) throw NetMsgError(NetMsgError::ERROR_NO_MEM);
00084 memset(buf,0,s);
00085 buf_len = s;
00086 pos = buf;
00087 buf_end = buf+(s-1);
00088 }
00089
00095 NetMsg::NetMsg(uchar *b, uint32 s, bool copy) {
00096 if (s>max_size) throw NetMsgError(NetMsgError::ERROR_TOO_LONG);
00097 if (s==0) throw NetMsgError(NetMsgError::ERROR_INVALID_BUFSIZE);
00098 if (copy) {
00099 buf = new(nothrow) uchar[s];
00100 if (!buf) throw NetMsgError(NetMsgError::ERROR_NO_MEM);
00101 memcpy(buf,b,s);
00102 } else {
00103 buf=b;
00104 if (!buf) throw NetMsgError(NetMsgError::ERROR_NULL_POINTER);
00105 }
00106 buf_len = s;
00107 pos = buf;
00108 buf_end = buf+(s-1);
00109 }
00110
00111 NetMsg::NetMsg(const NetMsg& n) {
00112 buf_len = n.buf_len;
00113 if (buf_len == 0)
00114 throw NetMsgError(NetMsgError::ERROR_INVALID_BUFSIZE);
00115
00116 buf = new(nothrow) uchar[buf_len];
00117 if (!buf) throw NetMsgError(NetMsgError::ERROR_NO_MEM);
00118 memcpy(buf,n.buf,buf_len);
00119 pos = buf+(n.pos-n.buf);
00120 buf_end = buf+(buf_len-1);
00121 }
00122
00124 NetMsg::~NetMsg() {
00125 if (buf) { delete[] buf; buf= 0; }
00126 }
00127
00129 uint32 NetMsg::get_size() const {
00130 return buf_len;
00131 }
00132
00136 uint32 NetMsg::get_bytes_left() const {
00137 if (buf<=pos)
00138 {
00139 if (pos<=buf_end)
00140 return (buf_end-pos)+1;
00141 else
00142 return 0;
00143 }
00144 else
00145 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00146 }
00147
00153 uint32 NetMsg::get_pos() const {
00154 if ((buf<=pos) && (pos<=(buf_end+1)))
00155 return (pos-buf);
00156 else
00157 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00158 }
00159
00165 NetMsg& NetMsg::set_pos(uint32 p) {
00166 if (p<=buf_len)
00167 {
00168 pos = buf+p;
00169 return *this;
00170 }
00171 else
00172 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00173 }
00174
00178 NetMsg& NetMsg::set_pos_r(int32 rp)
00179 {
00180 if (((pos+rp)>=buf) && ((pos+rp)<=(buf_end+1))) {
00181 pos += rp;
00182 }
00183 else
00184 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00185 return *this;
00186 }
00187
00189 NetMsg& NetMsg::to_start() {
00190 pos=buf;
00191 return *this;
00192 }
00193
00198 uint32 NetMsg::copy_from(const uchar *b, uint32 n) {
00199 return copy_from(b,0,n);
00200 }
00201
00207 uint32 NetMsg::copy_from(const uchar *b, uint32 start, uint32 n) {
00208 if ((n+start)>buf_len) throw NetMsgError(NetMsgError::ERROR_TOO_SHORT);
00209
00210
00211 memmove(buf+start,b,n);
00212 return n;
00213 }
00214
00221 uint32 NetMsg::copy_to(uchar *b, uint32 n) const {
00222 try {
00223 return copy_to(b,0,n);
00224 } catch(NetMsgError& e) {
00225
00226 }
00227 return 0;
00228 }
00229
00237 uint32 NetMsg::copy_to(uchar *b, uint32 start, uint32 n) const {
00238 if (start>=buf_len) throw NetMsgError(NetMsgError::ERROR_INVALID_START_OFFSET);
00239 if ((n+start)>buf_len) n=buf_len-start;
00240 memmove(b,buf+start,n);
00241 return n;
00242 }
00243
00245 uchar* NetMsg::get_buffer() const {
00246 return buf;
00247 }
00248
00249
00250
00254 uint8 NetMsg::decode8(bool move) {
00255 register uint8 i;
00256 if (pos<=buf_end)
00257 {
00258 i = *pos;
00259 if (move) pos+=1;
00260 }
00261 else
00262 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00263
00264 return i;
00265 }
00266
00270 uint16 NetMsg::decode16(bool move) {
00271 register uint16 i;
00272 if ((pos+1)<=buf_end) {
00273 i = ntohs(*((uint16*)pos));
00274 if (move) pos+=2;
00275 }
00276 else
00277 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00278 return i;
00279 }
00280
00284 uint32 NetMsg::decode32(bool move) {
00285 register uint32 i;
00286 if ((pos+3)<=buf_end) {
00287 i = ntohl(*((uint32*)pos));
00288 if (move) pos+=4;
00289 }
00290 else
00291 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00292 return i;
00293 }
00294
00298 uint64 NetMsg::decode64(bool move) {
00299 uint64 hi = 0;
00300 uint64 lo = 0;
00301 uint64 res = 0;
00302 uint32* p = (uint32*)pos;
00303 if ((pos+7)<=buf_end) {
00304 hi = ntohl(*p);
00305 lo = ntohl(*(p+1));
00306 res = (hi<<32)+lo;
00307 if (move) pos+=8;
00308 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00309 return res;
00310 }
00311
00315 uint128 NetMsg::decode128(bool move) {
00316 uint32 word1, word2, word3, word4;
00317 uint128 res;
00318 word1 = NetMsg::decode32();
00319 word2 = NetMsg::decode32();
00320 word3 = NetMsg::decode32();
00321 word4 = NetMsg::decode32();
00322 res.w1 = word1;
00323 res.w2 = word2;
00324 res.w3 = word3;
00325 res.w4 = word4;
00326
00327 return res;
00328 }
00329
00334 void NetMsg::encode8(uint8 i, bool move) {
00335 if (pos<=buf_end) {
00336 *pos = i;
00337 if (move) pos+=1;
00338 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00339 }
00340
00345 void NetMsg::encode16(uint16 i, bool move) {
00346 if ((pos+1)<=buf_end) {
00347 *((uint16*)pos) = htons(i);
00348 if (move) pos+=2;
00349 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00350 }
00351
00356 void NetMsg::encode32(uint32 i, bool move) {
00357 if ((pos+3)<=buf_end) {
00358 *((uint32*)pos) = htonl(i);
00359 if (move) pos+=4;
00360 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00361 }
00362
00367 void NetMsg::encode64(uint64 i, bool move) {
00368 uint32 hi = 0;
00369 uint32 lo = 0;
00370 uint32* p = (uint32*)pos;
00371 if ((pos+7)<=buf_end) {
00372 lo = i;
00373 hi = (i>>32);
00374 *p = htonl(hi);
00375 *(p+1) = htonl(lo);
00376 if (move) pos+=8;
00377 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00378 }
00379
00384 void NetMsg::encode128(uint128 i, bool move) {
00385 encode32(i.w1);
00386 encode32(i.w2);
00387 encode32(i.w3);
00388 encode32(i.w4);
00389 }
00390
00396 void NetMsg::decode(uchar *c, uint32 len, bool move) {
00397 if ((pos+(len-1))<=buf_end) {
00398 memmove(c,pos,len);
00399 if (move) pos+=len;
00400 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00401 }
00402
00408 void NetMsg::encode(const uchar *c, uint32 len, bool move) {
00409 if ((pos+(len-1))<=buf_end) {
00410 memmove(pos,c,len);
00411 if (move) pos+=len;
00412 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00413 }
00414
00421 uint32 NetMsg::decode(string& s, uint32 len, bool move) {
00422 if (len==0) {
00423 s.clear();
00424 return 0;
00425 } else if ((pos+(len-1))<=buf_end) {
00426 s.clear();
00427 s.assign((const char*)pos,0,len);
00428 if (move) pos+=len;
00429 return s.length();
00430 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00431 }
00432
00437 uint32 NetMsg::encode(const string& s, bool move) {
00438 uint32 len = s.length();
00439 if ((pos+(len-1))<=buf_end) {
00440 memmove(pos,s.c_str(),len);
00441 if (move) pos+=len;
00442 return len;
00443 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00444 }
00445
00450 void NetMsg::decode(struct in_addr& in, bool move) {
00451
00452 if ((pos+3)<=buf_end) {
00453 in.s_addr = *((uint32*)pos);
00454 if (move) pos+=4;
00455 }
00456 else
00457 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00458 }
00459
00464 void NetMsg::encode(const struct in_addr& in, bool move) {
00465
00466 if ((pos+3)<=buf_end) {
00467 *((uint32*)pos) = in.s_addr;
00468 if (move) pos+=4;
00469 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00470 }
00471
00476 void NetMsg::decode(struct in6_addr& in, bool move) {
00477 if ((pos+15)<=buf_end) {
00478 memmove(in.s6_addr,pos,16);
00479 if (move) pos+=16;
00480 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00481 }
00482
00487 void NetMsg::encode(const struct in6_addr& in, bool move) {
00488 if ((pos+15)<=buf_end) {
00489 memmove(pos,in.s6_addr,16);
00490 if (move) pos+=16;
00491 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00492 }
00493
00494
00495
00496
00497
00498
00503 uint32 NetMsg::truncate() {
00504 if ((pos>=buf) && (pos<=(buf_end+1))) {
00505 buf_len = (pos-buf);
00506 buf_end = pos-1;
00507 to_start();
00508 } else {
00509 throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00510 }
00511 return buf_len;
00512 }
00513
00515 uint32 NetMsg::truncate(uint32 t) {
00516 set_pos(t);
00517 return truncate();
00518 }
00519
00524 void NetMsg::padding(uint32 len, bool move) {
00525 if (len==0) return;
00526 else if ((pos+(len-1))<=buf_end) {
00527 memset(pos,0,len);
00528 if (move) pos+=len;
00529 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00530 }
00531
00533 bool NetMsg::operator==(const NetMsg& n) const
00534 {
00535
00536 if (buf_len==n.buf_len)
00537 {
00538
00539 if ((buf==NULL) && (n.buf==NULL))
00540 return true;
00541 else
00542 if (buf && n.buf)
00543 {
00544
00545 if (memcmp(buf,n.buf,buf_len)==0)
00546 {
00547
00548 return ((pos-buf)==(n.pos-n.buf));
00549 }
00550 else
00551 return false;
00552 }
00553 else
00554 return false;
00555 }
00556 else
00557 return false;
00558 }
00559
00564 void NetMsg::decode(NetMsg& m, bool move) {
00565 uint32 len = m.get_size();
00566 if ((pos+(len-1))<=buf_end) {
00567
00568 m.to_start();
00569 memmove(m.buf,pos,len);
00570 if (move) pos+=len;
00571 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00572 }
00573
00579 void NetMsg::encode(const NetMsg& m, uint32 len, bool move) {
00580 if ((pos+(len-1))<=buf_end) {
00581 memmove(pos,m.buf,len);
00582 if (move) pos+=len;
00583 } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
00584 }
00585
00586
00590 ostream&
00591 NetMsg::hexdump(ostream& os, uchar *startpos, uint32 length) const
00592 {
00593 if (length==0)
00594 length=buf_len;
00595
00596 if (startpos == 0)
00597 startpos= buf;
00598
00599 ios_base::fmtflags flags = os.flags();
00600
00601 os << color[blue] << "[dump: start=" << static_cast<void *>(startpos) << ", length:" << length;
00602 if (startpos > buf_end)
00603 return os << "ERROR: start position behind last buffer byte ]" << color[clear] << endl;
00604 else
00605 if (startpos < buf)
00606 return os << "ERROR: start position before first buffer byte ]" << color[clear] << endl;
00607
00608 os << endl;
00609
00610 while ( length > 0 && startpos <= buf_end )
00611 {
00612 os << setw(4) << startpos-buf << ": ";
00613
00614
00615 for (uint8 index=0; index <= 3; index++) {
00616 if ( startpos+index <= buf_end ) {
00617 uchar c = *(startpos+index);
00618 os << ( isalnum(c) ? static_cast<char>(c) : '.');
00619 }
00620 else
00621 os << ' ';
00622 }
00623
00624 os << " : " << hex << noshowbase;
00625
00626
00627 for (uint8 index=0; index <= 3; index++) {
00628 if ( startpos+index <= buf_end )
00629 os << setw(2) << setfill('0')
00630 << static_cast<unsigned short>(*(startpos+index)) << ' ';
00631 else
00632 os << " ";
00633 }
00634
00635 os << setfill(' ') << " ";
00636
00637
00638 for (uint8 index=0; index <= 3 && (startpos+index <= buf_end); index++)
00639 {
00640 unsigned short val = static_cast<unsigned short>(*(startpos+index));
00641
00642 for (int i=7; i >= 0; i--)
00643 os << ((val >> i) & 1);
00644
00645 os << ' ';
00646 }
00647
00648 startpos += 4;
00649 length = ( length >= 4 ) ? length-4 : 0;
00650
00651
00652 os.width(0);
00653 os << dec << setfill(' ') << endl;
00654 }
00655
00656 os.setf(flags);
00657
00658 return os << ']' << color[clear] << endl;
00659 }
00660
00661 ostream& operator<<(ostream& os, NetMsg& msg)
00662 {
00663
00664 ostringstream hexdumpstr;
00665 msg.hexdump(hexdumpstr);
00666 return os << hexdumpstr.str();
00667
00668 }
00669
00671
00672 }