TURN Server  1.5
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines
src/client++/TurnMsgLib.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012, 2013 Citrix Systems
00003  *
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the project nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  */
00030 
00031 #ifndef __LIB_TURN_MSG_CPP__
00032 #define __LIB_TURN_MSG_CPP__
00033 
00034 #include "ns_turn_ioaddr.h"
00035 #include "ns_turn_msg.h"
00036 
00037 #include <string>
00038 
00039 namespace turn {
00040 
00041 class StunAttr;
00042 
00046 class EndOfStunMsgException {
00047 public:
00048         EndOfStunMsgException() {}
00049         virtual ~EndOfStunMsgException() {}
00050 };
00051 
00055 class WrongStunAttrFormatException {
00056 public:
00057         WrongStunAttrFormatException() {}
00058         virtual ~WrongStunAttrFormatException() {}
00059 };
00060 
00064 class WrongStunBufferFormatException {
00065 public:
00066         WrongStunBufferFormatException() {}
00067         virtual ~WrongStunBufferFormatException() {}
00068 };
00069 
00073 class StunAttrIterator {
00074 public:
00078         StunAttrIterator(u08bits *buf, size_t sz) throw (WrongStunBufferFormatException) :
00079                 _buf(buf), _sz(sz)  {
00080                 if(!stun_is_command_message_str(_buf, _sz)) {
00081                         throw WrongStunBufferFormatException();
00082                 }
00083                 _sar = stun_attr_get_first_str(_buf, _sz);
00084         }
00085 
00089         template<class T>
00090         StunAttrIterator(T &msg) throw (WrongStunBufferFormatException) :
00091                 _buf(msg.getRawBuffer()), _sz(msg.getSize())  {
00092                 if(!stun_is_command_message_str(_buf, _sz)) {
00093                         throw WrongStunBufferFormatException();
00094                 }
00095                 _sar = stun_attr_get_first_str(_buf, _sz);
00096         }
00097 
00102         StunAttrIterator(u08bits *buf, size_t sz, u16bits attr_type) throw (WrongStunBufferFormatException) :
00103                         _buf(buf), _sz(sz)  {
00104                 if(!stun_is_command_message_str(_buf, _sz)) {
00105                         throw WrongStunBufferFormatException();
00106                 }
00107                 _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type);
00108         }
00109 
00114         template<class T>
00115         StunAttrIterator(T &msg, u16bits attr_type) throw (WrongStunBufferFormatException) :
00116                         _buf(msg.getRawBuffer()), _sz(msg.getSize())  {
00117                 if(!stun_is_command_message_str(_buf, _sz)) {
00118                         throw WrongStunBufferFormatException();
00119                 }
00120                 _sar = stun_attr_get_first_by_type_str(_buf, _sz, attr_type);
00121         }
00122 
00126         void next() throw(EndOfStunMsgException) {
00127                 if(!_sar) {
00128                         throw EndOfStunMsgException();
00129                 }
00130                 _sar = stun_attr_get_next_str(_buf,_sz,_sar);
00131         }
00132 
00136         bool eof() const {
00137                 return (!_sar);
00138         }
00139 
00143         bool isAddr() const {
00144                 return stun_attr_is_addr(_sar);
00145         }
00146 
00150         int getAddressFamily() const {
00151                 return stun_get_requested_address_family(_sar);
00152         }
00153 
00157         int getType() const {
00158                 return stun_attr_get_type(_sar);
00159         }
00160 
00164         virtual ~StunAttrIterator() {}
00165 
00170         const u08bits *getRawBuffer(size_t &sz) const throw(WrongStunAttrFormatException) {
00171                 int len = stun_attr_get_len(_sar);
00172                 if(len<0)
00173                         throw WrongStunAttrFormatException();
00174                 sz = (size_t)len;
00175                 const u08bits *value = stun_attr_get_value(_sar);
00176                 return value;
00177         }
00178         friend class StunAttr;
00179 private:
00180         u08bits *_buf;
00181         size_t _sz;
00182         stun_attr_ref _sar;
00183 };
00184 
00189 class StunAttr {
00190 public:
00194         StunAttr() : _attr_type(0), _value(0), _sz(0) {}
00195 
00199         StunAttr(const StunAttrIterator &iter) throw(WrongStunAttrFormatException, EndOfStunMsgException) {
00200                 if(iter.eof()) {
00201                         throw EndOfStunMsgException();
00202                 }
00203                 size_t sz = 0;
00204                 const u08bits *ptr = iter.getRawBuffer(sz);
00205                 if(sz>=0xFFFF)
00206                         throw WrongStunAttrFormatException();
00207                 int at = iter.getType();
00208                 if(at<0)
00209                         throw WrongStunAttrFormatException();
00210                 _attr_type = (u16bits)at;
00211                 _sz = sz;
00212                 _value=(u08bits*)turn_malloc(_sz);
00213                 if(ptr)
00214                         ns_bcopy(ptr,_value,_sz);
00215         }
00216 
00220         virtual ~StunAttr() {
00221                 if(_value)
00222                         turn_free(_value,_sz);
00223         }
00224 
00228         const u08bits *getRawValue(size_t &sz) const {
00229                 sz=_sz;
00230                 return _value;
00231         }
00232 
00236         void setRawValue(u08bits *value, size_t sz) throw(WrongStunAttrFormatException) {
00237                 if(sz>0xFFFF)
00238                         throw WrongStunAttrFormatException();
00239                 if(_value)
00240                         turn_free(_value,_sz);
00241                 _sz = sz;
00242                 _value=(u08bits*)turn_malloc(_sz);
00243                 if(value)
00244                         ns_bcopy(value,_value,_sz);
00245         }
00246 
00250         u16bits getType() const {
00251                 return _attr_type;
00252         }
00253 
00257         void setType(u16bits at) {
00258                 _attr_type = at;
00259         }
00260 
00264         template<class T>
00265         int addToMsg(T &msg) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00266                 if(!_attr_type)
00267                         throw WrongStunAttrFormatException();
00268                 u08bits *buffer = msg.getRawBuffer();
00269                 if(buffer) {
00270                         size_t sz = msg.getSize();
00271                         if(addToBuffer(buffer, sz)<0) {
00272                                 throw WrongStunBufferFormatException();
00273                         }
00274                         msg.setSize(sz);
00275                         return 0;
00276                 }
00277                 throw WrongStunBufferFormatException();
00278         }
00279 protected:
00280 
00284         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00285                 if(buffer) {
00286                         if(!_value)
00287                                 throw WrongStunAttrFormatException();
00288                         if(stun_attr_add_str(buffer, &sz, _attr_type, _value, _sz)<0) {
00289                                 throw WrongStunBufferFormatException();
00290                         }
00291                         return 0;
00292                 }
00293                 throw WrongStunBufferFormatException();
00294         }
00295 
00299         static stun_attr_ref getSar(const StunAttrIterator &iter) {
00300                 return iter._sar;
00301         }
00302 private:
00303         u16bits _attr_type;
00304         u08bits *_value;
00305         size_t _sz;
00306 };
00307 
00311 class StunAttrChannelNumber : public StunAttr {
00312 public:
00313         StunAttrChannelNumber() : _cn(0) {
00314                 setType(STUN_ATTRIBUTE_CHANNEL_NUMBER);
00315         }
00316         StunAttrChannelNumber(const StunAttrIterator &iter)
00317                 throw(WrongStunAttrFormatException, EndOfStunMsgException) :
00318                 StunAttr(iter) {
00319 
00320                 if(iter.eof())
00321                         throw EndOfStunMsgException();
00322                 _cn = stun_attr_get_channel_number(getSar(iter));
00323                 if(!_cn)
00324                         throw WrongStunAttrFormatException();
00325         }
00326         virtual ~StunAttrChannelNumber() {}
00327         u16bits getChannelNumber() const {
00328                 return _cn;
00329         }
00330         void setChannelNumber(u16bits cn) {
00331                 _cn = cn;
00332         }
00333 protected:
00334         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00335                 return stun_attr_add_channel_number_str(buffer,&sz,_cn);
00336         }
00337 private:
00338         u16bits _cn;
00339 };
00340 
00344 class StunAttrEvenPort : public StunAttr {
00345 public:
00346         StunAttrEvenPort() : _ep(0) {
00347                 setType(STUN_ATTRIBUTE_EVEN_PORT);
00348         }
00349         StunAttrEvenPort(const StunAttrIterator &iter)
00350                 throw(WrongStunAttrFormatException, EndOfStunMsgException) :
00351                 StunAttr(iter) {
00352 
00353                 if(iter.eof())
00354                         throw EndOfStunMsgException();
00355                 _ep = stun_attr_get_even_port(getSar(iter));
00356         }
00357         virtual ~StunAttrEvenPort() {}
00358         u08bits getEvenPort() const {
00359                 return _ep;
00360         }
00361         void setEvenPort(u08bits ep) {
00362                 _ep = ep;
00363         }
00364 protected:
00365         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00366                 return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_EVEN_PORT, &_ep, 1);
00367         }
00368 private:
00369         u08bits _ep;
00370 };
00371 
00375 class StunAttrReservationToken : public StunAttr {
00376 public:
00377         StunAttrReservationToken() : _rt(0) {
00378                 setType(STUN_ATTRIBUTE_RESERVATION_TOKEN);
00379         }
00380         StunAttrReservationToken(const StunAttrIterator &iter)
00381                 throw(WrongStunAttrFormatException, EndOfStunMsgException) :
00382                 StunAttr(iter) {
00383 
00384                 if(iter.eof())
00385                         throw EndOfStunMsgException();
00386                 _rt = stun_attr_get_reservation_token_value(getSar(iter));
00387         }
00388         virtual ~StunAttrReservationToken() {}
00389         u64bits getReservationToken() const {
00390                 return _rt;
00391         }
00392         void setReservationToken(u64bits rt) {
00393                 _rt = rt;
00394         }
00395 protected:
00396         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00397                 uint64_t reservation_token = ioa_ntoh64(_rt);
00398                 return stun_attr_add_str(buffer, &sz, STUN_ATTRIBUTE_RESERVATION_TOKEN, (u08bits*) (&reservation_token), 8);
00399         }
00400 private:
00401         u64bits _rt;
00402 };
00403 
00407 class StunAttrAddr : public StunAttr {
00408 public:
00409         StunAttrAddr(u16bits attr_type = 0) {
00410                 addr_set_any(&_addr);
00411                 setType(attr_type);
00412         }
00413         StunAttrAddr(const StunAttrIterator &iter)
00414                 throw(WrongStunAttrFormatException, EndOfStunMsgException) :
00415                 StunAttr(iter) {
00416 
00417                 if(iter.eof())
00418                         throw EndOfStunMsgException();
00419                 size_t sz = 0;
00420                 const u08bits *buf = iter.getRawBuffer(sz);
00421                 if(stun_attr_get_addr_str(buf,sz,getSar(iter),&_addr,NULL)<0) {
00422                         throw WrongStunAttrFormatException();
00423                 }
00424         }
00425         virtual ~StunAttrAddr() {}
00426         void getAddr(ioa_addr &addr) const {
00427                 addr_cpy(&addr,&_addr);
00428         }
00429         void setAddr(ioa_addr &addr) {
00430                 addr_cpy(&_addr,&addr);
00431         }
00432 protected:
00433         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00434                 return stun_attr_add_addr_str(buffer, &sz, getType(), &_addr);
00435         }
00436 private:
00437         ioa_addr _addr;
00438 };
00439 
00443 class StunAttrChangeRequest : public StunAttr {
00444 public:
00445         StunAttrChangeRequest() : _changeIp(0), _changePort(0) {
00446                 setType(STUN_ATTRIBUTE_CHANGE_REQUEST);
00447         }
00448         StunAttrChangeRequest(const StunAttrIterator &iter)
00449                 throw(WrongStunAttrFormatException, EndOfStunMsgException) :
00450                 StunAttr(iter) {
00451 
00452                 if(iter.eof())
00453                         throw EndOfStunMsgException();
00454 
00455                 if(stun_attr_get_change_request_str(getSar(iter), &_changeIp, &_changePort)<0) {
00456                         throw WrongStunAttrFormatException();
00457                 }
00458         }
00459         virtual ~StunAttrChangeRequest() {}
00460         bool getChangeIp() const {
00461                 return _changeIp;
00462         }
00463         void setChangeIp(bool ci) {
00464                 if(ci)
00465                         _changeIp = 1;
00466                 else
00467                         _changeIp = 0;
00468         }
00469         bool getChangePort() const {
00470                 return _changePort;
00471         }
00472         void setChangePort(bool cp) {
00473                 if(cp)
00474                         _changePort = 1;
00475                 else
00476                         _changePort = 0;
00477         }
00478 protected:
00479         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00480                 return stun_attr_add_change_request_str(buffer, &sz, _changeIp, _changePort);
00481         }
00482 private:
00483         int _changeIp;
00484         int _changePort;
00485 };
00486 
00490 class StunAttrResponsePort : public StunAttr {
00491 public:
00492         StunAttrResponsePort() : _rp(0) {
00493                 setType(STUN_ATTRIBUTE_RESPONSE_PORT);
00494         }
00495         StunAttrResponsePort(const StunAttrIterator &iter)
00496                 throw(WrongStunAttrFormatException, EndOfStunMsgException) :
00497                 StunAttr(iter) {
00498 
00499                 if(iter.eof())
00500                         throw EndOfStunMsgException();
00501 
00502                 int rp = stun_attr_get_response_port_str(getSar(iter));
00503                 if(rp<0) {
00504                         throw WrongStunAttrFormatException();
00505                 }
00506                 _rp = (u16bits)rp;
00507         }
00508         virtual ~StunAttrResponsePort() {}
00509         u16bits getResponsePort() const {
00510                 return _rp;
00511         }
00512         void setResponsePort(u16bits p) {
00513                 _rp = p;
00514         }
00515 protected:
00516         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00517                 return stun_attr_add_response_port_str(buffer, &sz, _rp);
00518         }
00519 private:
00520         u16bits _rp;
00521 };
00522 
00526 class StunAttrPadding : public StunAttr {
00527 public:
00528         StunAttrPadding() : _p(0) {
00529                 setType(STUN_ATTRIBUTE_PADDING);
00530         }
00531         StunAttrPadding(const StunAttrIterator &iter)
00532                 throw(WrongStunAttrFormatException, EndOfStunMsgException) :
00533                 StunAttr(iter) {
00534 
00535                 if(iter.eof())
00536                         throw EndOfStunMsgException();
00537 
00538                 int p = stun_attr_get_padding_len_str(getSar(iter));
00539                 if(p<0) {
00540                         throw WrongStunAttrFormatException();
00541                 }
00542                 _p = (u16bits)p;
00543         }
00544         virtual ~StunAttrPadding() {}
00545         u16bits getPadding() const {
00546                 return _p;
00547         }
00551         void setPadding(u16bits p) {
00552                 _p = p;
00553         }
00554 protected:
00555         virtual int addToBuffer(u08bits *buffer, size_t &sz) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00556                 return stun_attr_add_padding_str(buffer, &sz, _p);
00557         }
00558 private:
00559         u16bits _p;
00560 };
00561 
00565 class StunMsg {
00566 public:
00570         StunMsg() {
00571                 _allocated_sz = 0xFFFF;
00572                 _buffer = (u08bits*)turn_malloc(_allocated_sz);
00573                 _deallocate = true;
00574                 _sz = 0;
00575                 _constructed = 0;
00576         }
00577 
00582         StunMsg(u08bits *buffer, size_t total_sz, size_t sz, bool constructed) :
00583                 _buffer(buffer), _deallocate(false), _allocated_sz(total_sz),
00584                 _sz(sz), _constructed(constructed) {}
00585 
00589         virtual ~StunMsg() {
00590                 if(_deallocate && _buffer) {
00591                         turn_free(_buffer, _allocated_sz);
00592                 }
00593         }
00594 
00598         void construct() {
00599                 constructBuffer();
00600         }
00601 
00605         bool isValid() {
00606                 return check();
00607         }
00608 
00612         u08bits *getRawBuffer() {
00613                 return _buffer;
00614         }
00615 
00619         size_t getSize() const {
00620                 return _sz;
00621         }
00622 
00626         void setSize(size_t sz) throw(WrongStunBufferFormatException) {
00627                 if(sz>_allocated_sz)
00628                         throw WrongStunBufferFormatException();
00629                 _sz = sz;
00630         }
00631 
00635         static bool isCommand(u08bits *buffer, size_t sz) {
00636                 return stun_is_command_message_str(buffer, sz);
00637         }
00638 
00642         bool isCommand() const {
00643                 return stun_is_command_message_str(_buffer, _sz);
00644         }
00645 
00646         static bool isIndication(u08bits *buffer, size_t sz) {
00647                 return stun_is_indication_str(buffer, sz);
00648         }
00649 
00650         static bool isRequest(u08bits *buffer, size_t sz) {
00651                 return stun_is_request_str(buffer, sz);
00652         }
00653 
00654         static bool isSuccessResponse(u08bits *buffer, size_t sz) {
00655                 return stun_is_success_response_str(buffer, sz);
00656         }
00657 
00658         static bool isErrorResponse(u08bits *buffer, size_t sz,
00659                                         int &err_code, u08bits *err_msg, size_t err_msg_size) {
00660                 return stun_is_error_response_str(buffer, sz, &err_code, err_msg, err_msg_size);
00661         }
00662 
00666         static bool isChallengeResponse(const u08bits* buf, size_t sz,
00667                                         int &err_code, u08bits *err_msg, size_t err_msg_size,
00668                                         u08bits *realm, u08bits *nonce) {
00669                 return stun_is_challenge_response_str(buf, sz, &err_code, err_msg, err_msg_size, realm, nonce);
00670         }
00671 
00675         static bool isChannel(u08bits *buffer, size_t sz) {
00676                 return is_channel_msg_str(buffer, sz);
00677         }
00678 
00682         static bool isFingerprintPresent(u08bits *buffer, size_t sz) {
00683                 if(!stun_is_command_message_str(buffer,sz))
00684                         return false;
00685                 stun_attr_ref sar = stun_attr_get_first_by_type_str(buffer, sz, STUN_ATTRIBUTE_FINGERPRINT);
00686                 if(!sar)
00687                         return false;
00688 
00689                 return true;
00690         }
00691 
00695         static bool checkFingerprint(u08bits *buffer, size_t sz) {
00696                 return stun_is_command_message_full_check_str(buffer, sz, 1);
00697         }
00698 
00702         int addAttr(StunAttr &attr) throw(WrongStunAttrFormatException, WrongStunBufferFormatException) {
00703                 return attr.addToMsg(*this);
00704         }
00705 
00709         virtual stun_tid getTid() const throw(WrongStunBufferFormatException) {
00710                 if(!_constructed || !isCommand())
00711                         throw WrongStunBufferFormatException();
00712                 stun_tid tid;
00713                 stun_tid_from_message_str(_buffer,_sz,&tid);
00714                 return tid;
00715         }
00716 
00720         virtual void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) {
00721                 if(!_constructed || !isCommand())
00722                         throw WrongStunBufferFormatException();
00723                 stun_tid_message_cpy(_buffer, &tid);
00724         }
00725 
00729         void addFingerprint() throw(WrongStunBufferFormatException) {
00730                 if(!_constructed || !isCommand())
00731                         throw WrongStunBufferFormatException();
00732                 stun_attr_add_fingerprint_str(_buffer,&_sz);
00733         }
00734 
00738         bool checkMessageIntegrity(std::string &uname, std::string &realm, std::string &upwd) const
00739                 throw(WrongStunBufferFormatException) {
00740                 if(!_constructed || !isCommand())
00741                         throw WrongStunBufferFormatException();
00742                 return (0 == stun_check_message_integrity_str(_buffer, _sz,
00743                                 (u08bits *)uname.c_str(), (u08bits *)realm.c_str(), (u08bits *)upwd.c_str()));
00744         }
00745 
00749         void addMessageIntegrity(std::string &uname, std::string &realm, std::string &upwd, std::string &nonce)
00750                 throw(WrongStunBufferFormatException) {
00751 
00752                 if(!_constructed || !isCommand())
00753                         throw WrongStunBufferFormatException();
00754 
00755                 stun_attr_add_integrity_by_user_str(_buffer, &_sz,
00756                         (u08bits *)uname.c_str(), (u08bits *)realm.c_str(), (u08bits *)upwd.c_str(), (u08bits *)nonce.c_str());
00757         }
00758 
00759 protected:
00760         virtual void constructBuffer() = 0;
00761         virtual bool check() = 0;
00762 protected:
00763         u08bits *_buffer;
00764         bool _deallocate;
00765         size_t _allocated_sz;
00766         size_t _sz;
00767         bool _constructed;
00768 };
00769 
00773 class StunMsgRequest : public StunMsg {
00774 public:
00775         StunMsgRequest(u16bits method) : _method(method) {};
00776         StunMsgRequest(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
00777                 throw(WrongStunBufferFormatException) :
00778                         StunMsg(buffer,total_sz,sz,constructed),_method(0) {
00779 
00780                 if(constructed) {
00781                         if(!stun_is_request_str(buffer,sz)) {
00782                                 throw WrongStunBufferFormatException();
00783                         }
00784                         _method = stun_get_method_str(buffer,sz);
00785                 }
00786         }
00787         virtual ~StunMsgRequest() {}
00788 
00792         u16bits getMethod() const {
00793                 return _method;
00794         }
00795 
00799         void setMethod(u16bits method) {
00800                 _method = method;
00801         }
00802 
00806         void constructBindingRequest() {
00807                 stun_set_binding_request_str(_buffer, &_sz);
00808         }
00809 
00810         bool isBindingRequest() const {
00811                 return stun_is_binding_request_str(_buffer,_sz,0);
00812         }
00813 
00817         void constructAllocateRequest(u32bits lifetime, int address_family) {
00818                 stun_set_allocate_request_str(_buffer, &_sz, lifetime, address_family);
00819         }
00820 
00824         void constructChannelBindRequest(const ioa_addr &peer_addr, u16bits channel_number) {
00825                 stun_set_channel_bind_request_str(_buffer, &_sz,
00826                                         &peer_addr, channel_number);
00827         }
00828 
00829 protected:
00830         virtual void constructBuffer() {
00831                 stun_init_request_str(_method,_buffer,&_sz);
00832                 _constructed = true;
00833         }
00834 
00835         virtual bool check() {
00836                 if(!_constructed)
00837                         return false;
00838                 if(!stun_is_request_str(_buffer,_sz)) {
00839                         return false;
00840                 }
00841                 if(_method != stun_get_method_str(_buffer,_sz)) {
00842                         return false;
00843                 }
00844                 return true;
00845         }
00846 
00847 private:
00848         u16bits _method;
00849 };
00850 
00854 class StunMsgResponse : public StunMsg {
00855 public:
00856         StunMsgResponse(u16bits method, stun_tid &tid) : _method(method), _err(0), _reason(""), _tid(tid) {};
00857         StunMsgResponse(u16bits method, int error_code, std::string reason, stun_tid &tid) :
00858                 _method(method), _err(error_code), _reason(reason), _tid(tid) {
00859 
00860         };
00861         StunMsgResponse(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
00862                 throw(WrongStunBufferFormatException) :
00863                         StunMsg(buffer,total_sz,sz,constructed),_method(0),_err(0),_reason("") {
00864 
00865                 if(constructed) {
00866                         if(!stun_is_success_response_str(buffer,sz)) {
00867                                 u08bits errtxt[0xFFFF];
00868                                 if(!stun_is_error_response_str(buffer,sz,&_err,errtxt,sizeof(errtxt))) {
00869                                         throw WrongStunBufferFormatException();
00870                                 }
00871                                 _reason = (char*)errtxt;
00872                         }
00873                         _method = stun_get_method_str(buffer,sz);
00874                         stun_tid_from_message_str(_buffer,_sz,&_tid);
00875                 }
00876         }
00877 
00878         u16bits getMethod() const {
00879                 return _method;
00880         }
00881 
00882         void setMethod(u16bits method) {
00883                 _method = method;
00884         }
00885 
00889         int getError() const {
00890                 return _err;
00891         }
00892 
00896         void setError(int err) {
00897                 _err = err;
00898         }
00899 
00903         std::string getReason() const {
00904                 return _reason;
00905         }
00906 
00910         void setReason(std::string reason) {
00911                 _reason = reason;
00912         }
00913 
00917         void setTid(stun_tid &tid) throw(WrongStunBufferFormatException) {
00918                 _tid = tid;
00919         }
00920 
00924         stun_tid getTid() throw(WrongStunBufferFormatException) {
00925                 return _tid;
00926         }
00927 
00931         bool isChallenge(std::string &realm, std::string &nonce) const {
00932                 bool ret = false;
00933                 if(_constructed) {
00934                         int err_code;
00935                         u08bits err_msg[1025];
00936                         size_t err_msg_size=sizeof(err_msg);
00937                         u08bits srealm[0xFFFF];
00938                         u08bits snonce[0xFFFF];
00939                         ret = stun_is_challenge_response_str(_buffer, _sz, &err_code, err_msg, err_msg_size, srealm, snonce);
00940                         if(ret) {
00941                                 realm = (char*)srealm;
00942                                 nonce = (char*)snonce;
00943                         }
00944                 }
00945                 return ret;
00946         }
00947 
00948         bool isChallenge() const {
00949                 std::string realm, nonce;
00950                 return isChallenge(realm, nonce);
00951         }
00952 
00956         bool isSuccess() const {
00957                 return (_err == 0);
00958         }
00959 
00963         void constructBindingResponse(stun_tid &tid,
00964                                 const ioa_addr &reflexive_addr, int error_code,
00965                                 const u08bits *reason) {
00966 
00967                 stun_set_binding_response_str(_buffer, &_sz, &tid,
00968                                         &reflexive_addr, error_code,
00969                                         reason);
00970         }
00971 
00972         bool isBindingResponse() const {
00973                 return stun_is_binding_response_str(_buffer,_sz);
00974         }
00975 
00979         void constructAllocateResponse(stun_tid &tid,
00980                                            const ioa_addr &relayed_addr,
00981                                            const ioa_addr &reflexive_addr,
00982                                            u32bits lifetime, int error_code, const u08bits *reason,
00983                                            u64bits reservation_token) {
00984 
00985                 stun_set_allocate_response_str(_buffer, &_sz, &tid,
00986                                                    &relayed_addr,
00987                                                    &reflexive_addr,
00988                                                    lifetime, error_code, reason,
00989                                                    reservation_token);
00990         }
00991 
00995         void constructChannelBindResponse(stun_tid &tid, int error_code, const u08bits *reason) {
00996                 stun_set_channel_bind_response_str(_buffer, &_sz, &tid, error_code, reason);
00997         }
00998 
00999 protected:
01000         virtual void constructBuffer() {
01001                 if(_err) {
01002                         stun_init_error_response_str(_method, _buffer, &_sz, _err, (u08bits*)_reason.c_str(), &_tid);
01003                 } else {
01004                         stun_init_success_response_str(_method, _buffer, &_sz, &_tid);
01005                 }
01006                 _constructed = true;
01007         }
01008 
01009         virtual bool check() {
01010                 if(!_constructed)
01011                         return false;
01012                 if(!stun_is_success_response_str(_buffer,_sz)) {
01013                         u08bits errtxt[0xFFFF];
01014                         int cerr=0;
01015                         if(!stun_is_error_response_str(_buffer,_sz,&cerr,errtxt,sizeof(errtxt))) {
01016                                 throw WrongStunBufferFormatException();
01017                         }
01018                         if(cerr != _err) {
01019                                 throw WrongStunBufferFormatException();
01020                         }
01021                 }
01022                 if(_method != stun_get_method_str(_buffer,_sz)) {
01023                         return false;
01024                 }
01025                 return true;
01026         }
01027 
01028 private:
01029         u16bits _method;
01030         int _err;
01031         std::string _reason;
01032         stun_tid _tid;
01033 };
01034 
01038 class StunMsgIndication : public StunMsg {
01039 public:
01040         StunMsgIndication(u16bits method) : _method(method) {};
01041         StunMsgIndication(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
01042                 throw(WrongStunBufferFormatException) :
01043                         StunMsg(buffer,total_sz,sz,constructed),_method(0) {
01044 
01045                 if(constructed) {
01046                         if(!stun_is_indication_str(buffer,sz)) {
01047                                 throw WrongStunBufferFormatException();
01048                         }
01049                         _method = stun_get_method_str(buffer,sz);
01050                 }
01051         }
01052         virtual ~StunMsgIndication() {}
01053 
01054         u16bits getMethod() const {
01055                 return _method;
01056         }
01057 
01058         void setMethod(u16bits method) {
01059                 _method = method;
01060         }
01061 
01062 protected:
01063         virtual void constructBuffer() {
01064                 stun_init_indication_str(_method,_buffer,&_sz);
01065                 _constructed = true;
01066         }
01067 
01068         virtual bool check() {
01069                 if(!_constructed)
01070                         return false;
01071                 if(!stun_is_indication_str(_buffer,_sz)) {
01072                         return false;
01073                 }
01074                 if(_method != stun_get_method_str(_buffer,_sz)) {
01075                         return false;
01076                 }
01077                 return true;
01078         }
01079 
01080 private:
01081         u16bits _method;
01082 };
01083 
01087 class StunMsgChannel : public StunMsg {
01088 public:
01089         StunMsgChannel(u16bits cn, int length) : _cn(cn), _len(length) {};
01090         StunMsgChannel(u08bits *buffer, size_t total_sz, size_t sz, bool constructed)
01091                 throw(WrongStunBufferFormatException) :
01092                         StunMsg(buffer,total_sz,sz,constructed),_cn(0) {
01093 
01094                 if(constructed) {
01095                         if(!stun_is_channel_message_str(buffer,sz,&_cn)) {
01096                                 throw WrongStunBufferFormatException();
01097                         }
01098                         if(_sz>0xFFFF || _sz<4)
01099                                 throw WrongStunBufferFormatException();
01100 
01101                         _len = _sz-4;
01102                 } else {
01103                         if(total_sz>0xFFFF || total_sz<4)
01104                                 throw WrongStunBufferFormatException();
01105 
01106                         _len = 0;
01107                 }
01108         }
01109         virtual ~StunMsgChannel() {}
01110 
01111         u16bits getChannelNumber() const {
01112                 return _cn;
01113         }
01114 
01115         void setChannelNumber(u16bits cn) {
01116                 _cn = cn;
01117         }
01118 
01122         size_t getLength() const {
01123                 return _len;
01124         }
01125 
01129         void setLength(size_t len) {
01130                 _len = len;
01131         }
01132 
01133 protected:
01134         virtual void constructBuffer() {
01135                 stun_init_channel_message_str(_cn,_buffer,&_sz,(int)_len);
01136                 _constructed = true;
01137         }
01138 
01139         virtual bool check() {
01140                 if(!_constructed)
01141                         return false;
01142                 u16bits cn = 0;
01143                 if(!stun_is_channel_message_str(_buffer,_sz,&cn)) {
01144                         return false;
01145                 }
01146                 if(_cn != cn) {
01147                         return false;
01148                 }
01149                 return true;
01150         }
01151 
01152 private:
01153         u16bits _cn;
01154         size_t _len;
01155 };
01156 
01157 };
01158 /* namespace */
01159 
01160 #endif
01161 /* __LIB_TURN_MSG_CPP__ */