00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <arpa/inet.h>
00018
00019 #include "ProphetTLV.h"
00020 #include "HelloTLV.h"
00021 #include "RIBDTLV.h"
00022 #include "RIBTLV.h"
00023 #include "OfferTLV.h"
00024 #include "ResponseTLV.h"
00025 #include "Params.h"
00026
00027 namespace prophet
00028 {
00029
00030 ProphetTLV::ProphetTLV()
00031 : result_(UnknownResult), sender_instance_(0), receiver_instance_(0),
00032 tid_(0), length_(ProphetHeaderSize)
00033 {
00034 }
00035
00036 ProphetTLV::ProphetTLV(const std::string& src, const std::string& dst,
00037 header_result_t result, u_int16_t local_instance,
00038 u_int16_t remote_instance, u_int32_t tid)
00039 : src_(src), dst_(dst), result_(result),
00040 sender_instance_(local_instance),
00041 receiver_instance_(remote_instance), tid_(tid),
00042 length_(ProphetHeaderSize)
00043 {
00044 }
00045
00046 ProphetTLV::ProphetTLV(const ProphetTLV& p)
00047 : src_(p.src_), dst_(p.dst_), result_(p.result_),
00048 sender_instance_(p.sender_instance_),
00049 receiver_instance_(p.receiver_instance_),
00050 tid_(p.tid_), length_(p.length_)
00051 {
00052 list_.assign(p.list_.begin(),p.list_.end());
00053 }
00054
00055 ProphetTLV::~ProphetTLV()
00056 {
00057 for (iterator i = list_.begin(); i != list_.end(); i++)
00058 delete *i;
00059 }
00060
00061 size_t
00062 ProphetTLV::serialize(u_char* bp, size_t len) const
00063 {
00064
00065 if (bp == NULL) return 0;
00066
00067
00068 if (ProphetHeaderSize > len) return 0;
00069
00070
00071 length_ = 0;
00072
00073
00074 ProphetHeader* hdr = (ProphetHeader*) bp;
00075 memset(hdr,0,ProphetHeaderSize);
00076
00077
00078 bp += ProphetHeaderSize;
00079
00080
00081 for (const_iterator i = list_.begin(); i != list_.end(); i++)
00082 {
00083 BaseTLV* tlv = *i;
00084 size_t bytes_written = tlv->serialize(bp,len);
00085 if (bytes_written != tlv->length())
00086 break;
00087
00088 length_ += bytes_written;
00089 len -= bytes_written;
00090 bp += bytes_written;
00091 }
00092
00093
00094 if (ProphetHeaderSize > len) return 0;
00095
00096
00097 length_ += ProphetHeaderSize;
00098 len -= ProphetHeaderSize;
00099
00100 hdr->version = ProphetParams::PROPHET_VERSION;
00101 hdr->flags = 0;
00102 hdr->result = result_;
00103 hdr->code = 0;
00104 hdr->sender_instance = htons(sender_instance_);
00105 hdr->receiver_instance = htons(receiver_instance_);
00106 hdr->transaction_id = htonl(tid_);
00107 hdr->length = htons(length_);
00108
00109 return length_;
00110 }
00111
00112 ProphetTLV*
00113 ProphetTLV::deserialize(const std::string& src,
00114 const std::string& dst,
00115 const u_char* bp, size_t len)
00116 {
00117
00118 if (bp == NULL) return NULL;
00119
00120
00121 if (ProphetHeaderSize > len) return NULL;
00122
00123
00124 ProphetHeader* hdr = (ProphetHeader*) bp;
00125 if (hdr->version != ProphetParams::PROPHET_VERSION) return NULL;
00126 if (hdr->flags != 0) return NULL;
00127 if (hdr->code != 0) return NULL;
00128 if (static_cast<size_t>(ntohs(hdr->length)) > len) return NULL;
00129
00130
00131 ProphetTLV* p = new ProphetTLV();
00132 p->src_ = src;
00133 p->dst_ = dst;
00134 p->result_ = (header_result_t) hdr->result;
00135 p->sender_instance_ = ntohs(hdr->sender_instance);
00136 p->receiver_instance_ = ntohs(hdr->receiver_instance);
00137 p->tid_ = ntohl(hdr->transaction_id);
00138 bool submessage_flag = (hdr->submessage_flag == 0x1);
00139 u_int16_t submessage_num = ntohs(hdr->submessage_num);
00140
00141
00142 if (submessage_flag == true || submessage_num != 0)
00143 {
00144 delete p;
00145 return NULL;
00146 }
00147
00148
00149 p->length_ = ProphetHeaderSize;
00150 len -= ProphetHeaderSize;
00151 bp += ProphetHeaderSize;
00152
00153
00154 BaseTLV::prophet_tlv_t typecode = BaseTLV::UNKNOWN_TLV;
00155 BaseTLV* tlv = NULL;
00156 while (len > 0)
00157 {
00158 typecode = (BaseTLV::prophet_tlv_t)*bp;
00159 switch (typecode)
00160 {
00161 case BaseTLV::HELLO_TLV:
00162 tlv = TLVFactory<HelloTLV>::deserialize(bp,len);
00163 break;
00164 case BaseTLV::RIBD_TLV:
00165 tlv = TLVFactory<RIBDTLV>::deserialize(bp,len);
00166 break;
00167 case BaseTLV::RIB_TLV:
00168 tlv = TLVFactory<RIBTLV>::deserialize(bp,len);
00169 break;
00170 case BaseTLV::OFFER_TLV:
00171 tlv = TLVFactory<OfferTLV>::deserialize(bp,len);
00172 break;
00173 case BaseTLV::RESPONSE_TLV:
00174 tlv = TLVFactory<ResponseTLV>::deserialize(bp,len);
00175 break;
00176 default:
00177 tlv = NULL;
00178 break;
00179 }
00180 if (tlv == NULL) break;
00181
00182 p->add_tlv(tlv);
00183
00184 bp += tlv->length();
00185 len -= tlv->length();
00186 }
00187 return p;
00188 }
00189
00190 BaseTLV*
00191 ProphetTLV::get_tlv()
00192 {
00193 if (list_.empty())
00194 return NULL;
00195 BaseTLV* t = list_.front();
00196 list_.pop_front();
00197 return t;
00198 }
00199
00200 bool
00201 ProphetTLV::add_tlv(BaseTLV* tlv)
00202 {
00203
00204 if (tlv == NULL) return false;
00205
00206 length_ += tlv->length();
00207 list_.push_back(tlv);
00208 return true;
00209 }
00210
00211 };