00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <arpa/inet.h>
00018 #include "Util.h"
00019 #include "RIBDTLV.h"
00020
00021 namespace prophet
00022 {
00023
00024 RIBDTLV::RIBDTLV(const Dictionary& ribd)
00025 : BaseTLV(BaseTLV::RIBD_TLV), ribd_(ribd)
00026 {
00027 length_ = RIBDTLVHeaderSize;
00028 length_ += ribd_.guess_ribd_size(RoutingAddressStringSize);
00029 }
00030
00031 RIBDTLV::RIBDTLV()
00032 : BaseTLV(BaseTLV::RIBD_TLV) {}
00033
00034 size_t
00035 RIBDTLV::write_ras_entry(u_int16_t sid,
00036 const std::string& dest_id,
00037 u_char* bp, size_t len) const
00038 {
00039
00040 if (bp == NULL) return 0;
00041
00042
00043 size_t copylen = FOUR_BYTE_ALIGN(dest_id.length());
00044
00045
00046 if (RoutingAddressStringSize + copylen > len) return 0;
00047
00048
00049 size_t retval = RoutingAddressStringSize;
00050
00051
00052 RoutingAddressString* ras = (RoutingAddressString*) bp;
00053 ras->string_id = htons(sid);
00054 ras->length = dest_id.length() & 0xff;
00055 memcpy(&ras->ra_string[0],dest_id.c_str(),dest_id.length());
00056 retval += copylen;
00057
00058
00059 while (copylen-- > ras->length)
00060 ras->ra_string[copylen] = '\0';
00061
00062 return retval;
00063 }
00064
00065 size_t
00066 RIBDTLV::serialize(u_char* bp, size_t len) const
00067 {
00068
00069 if (bp == NULL) return 0;
00070 if (typecode_ != BaseTLV::RIBD_TLV) return 0;
00071
00072
00073 size_t ribd_sz = ribd_.guess_ribd_size(RoutingAddressStringSize);
00074 if (ribd_sz + RIBDTLVHeaderSize > len) return 0;
00075
00076
00077 size_t ribd_entry_count = 0;
00078 length_ = 0;
00079 RIBDTLVHeader* hdr = (RIBDTLVHeader*) bp;
00080 memset(hdr,0,RIBDTLVHeaderSize);
00081
00082
00083 bp += RIBDTLVHeaderSize;
00084 length_ += RIBDTLVHeaderSize;
00085
00086
00087 for (Dictionary::const_iterator i = ribd_.begin(); i != ribd_.end(); i++)
00088 {
00089
00090 if ((*i).first < 2)
00091 continue;
00092
00093 size_t bytes_written = 0;
00094 if ((bytes_written =
00095 write_ras_entry((*i).first,(*i).second,bp,len)) == 0)
00096 break;
00097
00098 bp += bytes_written;
00099 len -= bytes_written;
00100 length_ += bytes_written;
00101
00102 ribd_entry_count++;
00103 }
00104
00105
00106 hdr->type = BaseTLV::RIBD_TLV;
00107 hdr->flags = 0;
00108 hdr->length = htons(length_);
00109 hdr->entry_count = htons(ribd_entry_count);
00110
00111 return length_;
00112 }
00113
00114 size_t
00115 RIBDTLV::read_ras_entry(u_int16_t* sid,
00116 std::string& dest_id,
00117 const u_char* bp, size_t len)
00118 {
00119
00120 if (sid == NULL || bp == NULL) return 0;
00121
00122
00123 if (RoutingAddressStringSize > len) return 0;
00124
00125 RoutingAddressString* ras = (RoutingAddressString*) bp;
00126
00127
00128 size_t retval = RoutingAddressStringSize;
00129
00130
00131 size_t copylen = FOUR_BYTE_ALIGN(ras->length);
00132
00133
00134 if (copylen > len - retval) return retval;
00135
00136
00137 *sid = ntohs(ras->string_id);
00138 dest_id.assign((char*)&ras->ra_string[0],ras->length);
00139
00140
00141 retval += copylen;
00142
00143 return retval;
00144 }
00145
00146 bool
00147 RIBDTLV::deserialize(const u_char* bp, size_t len)
00148 {
00149 RIBDTLVHeader* hdr = (RIBDTLVHeader*) bp;
00150
00151
00152 if (bp == NULL) return false;
00153
00154
00155 if (hdr->type != RIBD_TLV) return false;
00156
00157
00158 if (len < RIBDTLVHeaderSize) return false;
00159
00160
00161 length_ = ntohs(hdr->length);
00162 if (len < length_) return false;
00163
00164 flags_ = hdr->flags;
00165
00166 size_t ribd_entry_count = ntohs(hdr->entry_count);
00167
00168
00169 bp += RIBDTLVHeaderSize;
00170
00171 size_t amt_read = RIBDTLVHeaderSize;
00172 len -= RIBDTLVHeaderSize;
00173
00174 u_int16_t sid;
00175 std::string dest_id;
00176 ribd_.clear();
00177 while (ribd_entry_count-- > 0)
00178 {
00179
00180 size_t bytes_read = read_ras_entry(&sid,dest_id,bp,len);
00181
00182
00183 if (bytes_read == 0) break;
00184
00185
00186 if(ribd_.assign(dest_id,sid) == false) break;
00187
00188 len -= bytes_read;
00189 bp += bytes_read;
00190 amt_read += bytes_read;
00191 }
00192
00193 return (amt_read == length_);
00194 }
00195
00196 const Dictionary&
00197 RIBDTLV::ribd(const std::string& sender, const std::string& receiver)
00198 {
00199 ribd_.assign(sender,0);
00200 ribd_.assign(receiver,1);
00201 return ribd_;
00202 }
00203
00204 };