Alexander Afanasyev | 6fbb7b4 | 2015-08-10 11:53:49 -0700 | [diff] [blame^] | 1 | -- Copyright (c) 2015, Regents of the University of California. |
| 2 | -- |
| 3 | -- This file is part of ndn-tools (Named Data Networking Essential Tools). |
| 4 | -- See AUTHORS.md for complete list of ndn-tools authors and contributors. |
| 5 | -- |
| 6 | -- ndn-tools is free software: you can redistribute it and/or modify it under the terms |
| 7 | -- of the GNU General Public License as published by the Free Software Foundation, |
| 8 | -- either version 3 of the License, or (at your option) any later version. |
| 9 | -- |
| 10 | -- ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
| 11 | -- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
| 12 | -- PURPOSE. See the GNU General Public License for more details. |
| 13 | -- |
| 14 | -- You should have received a copy of the GNU General Public License along with |
| 15 | -- ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| 16 | -- |
| 17 | -- @author Qi Zhao <https://www.linkedin.com/pub/qi-zhao/73/835/9a3> |
| 18 | -- @author Seunghyun Yoo <http://relue2718.com/> |
| 19 | -- @author Seungbae Kim <https://sites.google.com/site/sbkimcv/> |
| 20 | |
| 21 | |
| 22 | -- inspect.lua (https://github.com/kikito/inspect.lua) can be used for debugging. |
| 23 | -- See more at http://stackoverflow.com/q/15175859/2150331 |
| 24 | -- local inspect = require('inspect') |
| 25 | |
| 26 | -- NDN protocol |
| 27 | p_ndnproto = Proto ("ndn", "Named Data Network (NDN)") -- to create a 'Proto' object |
| 28 | |
| 29 | -- Type and Length fields |
| 30 | local f_packet_type = ProtoField.uint16("ndn.type", "Type", base.DEC_HEX) |
| 31 | local f_packet_size = ProtoField.uint16("ndn.length", "Length", base.DEC_HEX) |
| 32 | |
| 33 | -- Interest or Data packets |
| 34 | local f_interest = ProtoField.string("ndn.interest", "Interest", FT_STRING) |
| 35 | local f_data = ProtoField.string("ndn.data", "Data", FT_STRING) |
| 36 | |
| 37 | -- Name field |
| 38 | local f_name = ProtoField.string("ndn.name", "Name", FT_STRING) |
| 39 | local f_namecomponent = ProtoField.string("ndn.namecomponent", "Name Component", FT_STRING) |
| 40 | local f_implicitSHA = ProtoField.string("ndn.implicitsha", "Implicit SHA 256 Digest Component", FT_STRING) |
| 41 | |
| 42 | -- Sub-fields of Interest packet |
| 43 | local f_interest_selector = ProtoField.string("ndn.selector", "Selector", FT_STRING) |
| 44 | local f_interest_nonce = ProtoField.uint16("ndn.nonce", "Nonce", base.DEC_HEX) |
| 45 | local f_interest_scope = ProtoField.string("ndn.scope", "Scope", FT_STRING) |
| 46 | local f_interest_interestlifetime = ProtoField.uint16("ndn.interestlifetime", "Interest Life Time", base.DEC_HEX) |
| 47 | |
| 48 | -- Sub-fields of Interest/Selector field |
| 49 | local f_interest_selector_minsuffix = ProtoField.uint16("ndn.minsuffix", "Min Suffix Components", base.DEC_HEX) |
| 50 | local f_interest_selector_maxsuffix = ProtoField.uint16("ndn.maxsuffix", "Max Suffix Components", base.DEC_HEX) |
| 51 | local f_interest_selector_keylocator = ProtoField.string("ndn.keylocator", "Publisher Public Key Locator", FT_STRING) |
| 52 | local f_interest_selector_exclude = ProtoField.string("ndn.exclude", "Exclude", FT_STRING) |
| 53 | local f_interest_selector_childselector = ProtoField.uint16("ndn.childselector", "Child Selector", base.DEC_HEX) |
| 54 | local f_interest_selector_mustbefresh = ProtoField.string("ndn.mustbefresh", "Must Be Fresh", FT_STRING) |
| 55 | local f_interest_selector_any = ProtoField.string("ndn.any", "Any", FT_STRING) |
| 56 | |
| 57 | -- Sub-fields of Data packet |
| 58 | local f_data_metainfo = ProtoField.string("ndn.metainfo", "Meta Info", FT_STRING) |
| 59 | local f_data_content = ProtoField.string("ndn.content", "Content", FT_STRING) |
| 60 | local f_data_signatureinfo = ProtoField.string("ndn.signatureinfo", "Signature Info", FT_STRING) |
| 61 | local f_data_signaturevalue = ProtoField.string("ndn.signaturevalue", "Signature Value", FT_STRING) |
| 62 | |
| 63 | -- Sub-fields of Data/MetaInfo field |
| 64 | local f_data_metainfo_contenttype = ProtoField.uint16("ndn.contenttype", "Content Type", base.DEC_HEX) |
| 65 | local f_data_metainfo_freshnessperiod = ProtoField.uint16("ndn.freshnessperiod", "Freshness Period", base.DEC_HEX) |
| 66 | local f_data_metainfo_finalblockid = ProtoField.string("ndn.finalblockid", "Final Block ID", FT_STRING) |
| 67 | |
| 68 | -- Sub-fields of Data/Signature field |
| 69 | local f_data_signature_signaturetype = ProtoField.uint16("ndn.signaturetype", "Signature Type", base.DEC_HEX) |
| 70 | local f_data_signature_keylocator = ProtoField.string("ndn.keylocator", "Key Locator", FT_STRING) |
| 71 | local f_data_signature_keydigest = ProtoField.string("ndn.keydigest", "Key Digest", FT_STRING) |
| 72 | |
| 73 | -- Add protofields in NDN protocol |
| 74 | p_ndnproto.fields = {f_packet_type, f_packet_size, f_data, f_interest, f_name, f_namecomponent, f_implicitSHA, f_interest_selector, f_interest_nonce, f_interest_scope, f_interest_interestlifetime, f_interest_selector_mustbefresh, f_interest_selector_minsuffix, f_interest_selector_maxsuffix, f_interest_selector_keylocator, f_interest_selector_exclude, f_interest_selector_childselector, f_interest_selector_any, f_data_metainfo, f_data_content, f_data_signatureinfo, f_data_signaturevalue, f_data_metainfo_contenttype, f_data_metainfo_freshnessperiod, f_data_metainfo_finalblockid, f_data_signature_signaturetype, f_data_signature_keylocator, f_data_signature_keydigest} |
| 75 | |
| 76 | -- ndntlv_info = { data: { field, type, string }, children: {} } |
| 77 | |
| 78 | -- To handle the fragmented packets |
| 79 | -- type: map |
| 80 | -- * key: (host ip address, host port number) |
| 81 | -- * value: type: map |
| 82 | -- * key: packet number |
| 83 | -- * value: packet status |
| 84 | local pending_packets = {} |
| 85 | local CONST_STR_TRUNCATED = "TRUNCATED" |
| 86 | local CONST_STR_NDNTLV = "NDNTLV" |
| 87 | local GLOBAL_PACKET_INDEX = 0 |
| 88 | |
| 89 | function set_packet_status( packet_key, packet_number, status_key, status_value ) |
| 90 | if type( pending_packets[ packet_key ] ) ~= "table" then |
| 91 | pending_packets[ packet_key ] = {} |
| 92 | end |
| 93 | if type( pending_packets[ packet_key ][ packet_number ] ) ~= "table" then |
| 94 | pending_packets[ packet_key ][ packet_number ] = {} |
| 95 | end |
| 96 | pending_packets[ packet_key ][ packet_number ][ status_key ] = status_value |
| 97 | end |
| 98 | |
| 99 | function get_packet_status( packet_key, packet_number, status_key ) |
| 100 | if type( pending_packets[ packet_key ] ) ~= "table" then |
| 101 | return nil |
| 102 | end |
| 103 | if type( pending_packets[ packet_key ][ packet_number ] ) ~= "table" then |
| 104 | return nil |
| 105 | end |
| 106 | return pending_packets[ packet_key ][ packet_number ][ status_key ] |
| 107 | end |
| 108 | |
| 109 | function get_keys_from( table ) |
| 110 | local keyset = {} |
| 111 | local n = 0 |
| 112 | for k, v in pairs( table ) do |
| 113 | n = n + 1 |
| 114 | keyset[n] = k |
| 115 | end |
| 116 | return keyset |
| 117 | end |
| 118 | |
| 119 | function dump_packet_status() |
| 120 | --print(inspect(pending_packets)) |
| 121 | end |
| 122 | |
| 123 | function bytearray_to_int( raw_bytes, offset, length ) |
| 124 | local ret = 0 |
| 125 | for i = offset, offset + length - 1 do |
| 126 | ret = ret * 256 + raw_bytes:get_index( i ) |
| 127 | end |
| 128 | return ret |
| 129 | end |
| 130 | |
| 131 | function deepcopy(orig) |
| 132 | local orig_type = type(orig) |
| 133 | local copy |
| 134 | if orig_type == 'table' then |
| 135 | copy = {} |
| 136 | for orig_key, orig_value in next, orig, nil do |
| 137 | copy[deepcopy(orig_key)] = deepcopy(orig_value) |
| 138 | end |
| 139 | setmetatable(copy, deepcopy(getmetatable(orig))) |
| 140 | else -- number, string, boolean, etc |
| 141 | copy = orig |
| 142 | end |
| 143 | return copy |
| 144 | end |
| 145 | |
| 146 | function parse_ndn_tlv( packet_key, packet_number, is_original, max_size, optional_params, ndntlv_info ) |
| 147 | local raw_bytes = nil |
| 148 | local buf = nil |
| 149 | local length = nil |
| 150 | |
| 151 | if ( is_original ) then |
| 152 | buf = optional_params["buf"] |
| 153 | length = buf:len() |
| 154 | else |
| 155 | raw_bytes = optional_params["raw_bytes"] |
| 156 | length = raw_bytes:len() |
| 157 | end |
| 158 | |
| 159 | local current_pos = 0 |
| 160 | local _size_num_including_header = 0 |
| 161 | |
| 162 | local ret = true -- a result of a ndn-tlv parser |
| 163 | local isFirst = false -- flag that is going to be enabled when the first buffer arrives [BUGGY] |
| 164 | |
| 165 | while ( current_pos < length ) do |
| 166 | isFirst = ( current_pos == 0 ) |
| 167 | |
| 168 | -- extract TYPE |
| 169 | local _type_uint = nil |
| 170 | if ( is_original ) then |
| 171 | _type_uint = buf( current_pos, 1 ):uint() |
| 172 | else |
| 173 | _type_uint = bytearray_to_int( raw_bytes, current_pos, 1 ) |
| 174 | end |
| 175 | |
| 176 | -- print("type:" .. _type_uint) |
| 177 | |
| 178 | if ( isFirst ) then |
| 179 | _size_num_including_header = _size_num_including_header + 1 |
| 180 | end |
| 181 | current_pos = current_pos + 1 |
| 182 | |
| 183 | -- extract SIZE |
| 184 | local _size_num = nil |
| 185 | if ( is_original ) then |
| 186 | _size_num = buf( current_pos, 1 ):uint() |
| 187 | else |
| 188 | _size_num = bytearray_to_int( raw_bytes, current_pos, 1 ) |
| 189 | end |
| 190 | |
| 191 | if ( isFirst ) then |
| 192 | _size_num_including_header = _size_num_including_header + 1 |
| 193 | end |
| 194 | current_pos = current_pos + 1 |
| 195 | |
| 196 | if ( _size_num == 253 ) then |
| 197 | if ( is_original ) then |
| 198 | _size_num = buf( current_pos, 2 ):uint() |
| 199 | else |
| 200 | _size_num = bytearray_to_int( raw_bytes, current_pos, 2 ) |
| 201 | end |
| 202 | if ( isFirst ) then |
| 203 | _size_num_including_header = _size_num_including_header + _size_num + 2 |
| 204 | end |
| 205 | current_pos = current_pos + 2 |
| 206 | elseif ( _size_num == 254 ) then |
| 207 | if ( is_original ) then |
| 208 | _size_num = buf( current_pos, 4 ):uint() |
| 209 | else |
| 210 | _size_num = bytearray_to_int( raw_bytes, current_pos, 4 ) |
| 211 | end |
| 212 | if ( isFirst ) then |
| 213 | _size_num_including_header = _size_num_including_header + _size_num + 4 |
| 214 | end |
| 215 | current_pos = current_pos + 4 |
| 216 | elseif ( _size_num == 255 ) then |
| 217 | print("## error ## lua doesn't support 8 bytes of number variables.") |
| 218 | if ( is_original ) then |
| 219 | _size_num = buf( current_pos, 8 ):uint64() -- can lua number be larger than 32 bits? -- the type 'userdata' |
| 220 | else |
| 221 | _size_num = bytearray_to_int( raw_bytes, current_pos, 8 ) |
| 222 | end |
| 223 | if ( isFirst ) then |
| 224 | _size_num_including_header = _size_num_including_header + _size_num + 8 |
| 225 | end |
| 226 | current_pos = current_pos + 8 |
| 227 | else |
| 228 | if ( isFirst ) then |
| 229 | _size_num_including_header = _size_num_including_header + _size_num |
| 230 | end |
| 231 | end |
| 232 | |
| 233 | -- subtree:add( f_packet_size, _size ) |
| 234 | local type_size_info = " (Type: " .. _type_uint .. ", Size: " .. _size_num .. ")" |
| 235 | |
| 236 | -- need to check which one should be used: either _size_num or _size_num_including_header |
| 237 | if ( max_size ~= -1 and max_size < _size_num ) then |
| 238 | if ( is_original ) then |
| 239 | set_packet_status( packet_key, packet_number, "error", "The size of sub ndn-tlv packet can't exceed the parent's one." ) |
| 240 | end |
| 241 | ret = false |
| 242 | break |
| 243 | end |
| 244 | |
| 245 | if ( isFirst ) then |
| 246 | if ( is_original ) then |
| 247 | set_packet_status( packet_key, packet_number, "expected_size", _size_num_including_header ) |
| 248 | end |
| 249 | end |
| 250 | |
| 251 | if ( _type_uint == 18 ) then |
| 252 | if ( is_original ) then |
| 253 | set_packet_status( packet_key, packet_number, "error", "the type of field is 18 (but why is this an error?).") |
| 254 | end |
| 255 | return ret |
| 256 | end |
| 257 | |
| 258 | if ( current_pos + _size_num > length ) then |
| 259 | if ( is_original ) then |
| 260 | set_packet_status( packet_key, packet_number, "status", CONST_STR_TRUNCATED) |
| 261 | end |
| 262 | ret = false |
| 263 | break |
| 264 | end |
| 265 | |
| 266 | local _payload = nil |
| 267 | local new_optional_params = {} |
| 268 | if ( is_original ) then |
| 269 | _payload = buf( current_pos, _size_num ) |
| 270 | new_optional_params["buf"] = _payload |
| 271 | else |
| 272 | new_optional_params["raw_bytes"] = raw_bytes:subset( current_pos, _size_num ) |
| 273 | end |
| 274 | current_pos = current_pos + _size_num |
| 275 | |
| 276 | local child_tree = nil |
| 277 | |
| 278 | if ( _type_uint == 5 ) then -- interest packet can contain sub NDN-TLV packets |
| 279 | -- Interest packet |
| 280 | if ( is_original ) then |
| 281 | child_tree = add_subtree( ndntlv_info, { f_interest, _payload, type_size_info } ) |
| 282 | end |
| 283 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 284 | elseif ( _type_uint == 6 ) then |
| 285 | -- Data packet |
| 286 | if ( is_original ) then |
| 287 | child_tree = add_subtree( ndntlv_info, { f_data, _payload, type_size_info } ) |
| 288 | end |
| 289 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 290 | elseif ( _type_uint == 7 ) then |
| 291 | -- Name |
| 292 | if ( is_original ) then |
| 293 | child_tree = add_subtree( ndntlv_info, { f_name, _payload, type_size_info } ) |
| 294 | end |
| 295 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 296 | elseif ( _type_uint == 8 ) then |
| 297 | -- Name Component |
| 298 | if ( is_original ) then |
| 299 | add_subtree( ndntlv_info, { f_namecomponent, _payload, _payload:string(ENC_UTF_8) .. type_size_info } ) |
| 300 | end |
| 301 | elseif ( _type_uint == 1 ) then |
| 302 | -- Implicit SHA 256 Digest Component |
| 303 | if ( is_original ) then |
| 304 | add_subtree( ndntlv_info, { f_implicitSHA, _payload, _payload:string() .. type_size_info } ) |
| 305 | end |
| 306 | elseif ( _type_uint == 9 ) then |
| 307 | -- Selectors |
| 308 | if ( is_original ) then |
| 309 | child_tree = add_subtree( ndntlv_info, { f_interest_selector, _payload, type_size_info } ) |
| 310 | end |
| 311 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 312 | elseif ( _type_uint == 10 ) then |
| 313 | -- Nonce |
| 314 | if ( is_original ) then |
| 315 | add_subtree( ndntlv_info, { f_interest_nonce, _payload, _payload:uint(), nil, type_size_info } ) |
| 316 | end |
| 317 | elseif ( _type_uint == 11 ) then |
| 318 | -- Scope |
| 319 | if ( is_original ) then |
| 320 | add_subtree( ndntlv_info, { f_interest_scope, _payload, _payload:string() .. type_size_info } ) |
| 321 | end |
| 322 | elseif ( _type_uint == 12 ) then |
| 323 | -- Interest Lifetime |
| 324 | if ( is_original ) then |
| 325 | add_subtree( ndntlv_info, { f_interest_interestlifetime, _payload, _payload:uint(), nil, type_size_info } ) |
| 326 | end |
| 327 | elseif ( _type_uint == 13 ) then |
| 328 | -- Selectors / Min Suffix Components |
| 329 | if ( is_original ) then |
| 330 | add_subtree( ndntlv_info, { f_interest_selector_minsuffix, _payload, _payload:uint(), nil, type_size_info } ) |
| 331 | end |
| 332 | elseif ( _type_uint == 14 ) then |
| 333 | -- Selectors / Max Suffix Components |
| 334 | if ( is_original ) then |
| 335 | add_subtree( ndntlv_info, { f_interest_selector_maxsuffix, _payload, _payload:uint(), nil, type_size_info } ) |
| 336 | end |
| 337 | elseif ( _type_uint == 15 ) then |
| 338 | -- Selectors / Publish Key Locator |
| 339 | if ( is_original ) then |
| 340 | child_tree = add_subtree( ndntlv_info, { f_interest_selector_keylocator, _payload, type_size_info } ) |
| 341 | end |
| 342 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 343 | elseif ( _type_uint == 16 ) then |
| 344 | -- Selectors / Exclude |
| 345 | if ( is_original ) then |
| 346 | child_tree = add_subtree( ndntlv_info, { f_interest_selector_exclude, _payload, type_size_info } ) |
| 347 | end |
| 348 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 349 | elseif ( _type_uint == 17 ) then |
| 350 | -- Selectors / Child Selector |
| 351 | if ( is_original ) then |
| 352 | add_subtree( ndntlv_info, { f_interest_selector_childselector, _payload, _payload:uint(), nil, type_size_info } ) |
| 353 | end |
| 354 | elseif ( _type_uint == 18 ) then |
| 355 | -- Selectors / Must be Fresh |
| 356 | if ( is_original ) then |
| 357 | add_subtree( ndntlv_info, { f_interest_selector_mustbefresh, _payload, _payload:string() .. type_size_info } ) |
| 358 | end |
| 359 | elseif ( _type_uint == 19 ) then |
| 360 | -- Selectors / Any |
| 361 | if ( is_original ) then |
| 362 | add_subtree( ndntlv_info, { f_interest_selector_any, _payload, _payload:string() .. type_size_info } ) |
| 363 | end |
| 364 | elseif ( _type_uint == 20 ) then |
| 365 | -- MetaInfo |
| 366 | if ( is_original ) then |
| 367 | child_tree = add_subtree( ndntlv_info, { f_data_metainfo, _payload, type_size_info } ) |
| 368 | end |
| 369 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 370 | elseif ( _type_uint == 21 ) then |
| 371 | -- Content |
| 372 | if ( is_original ) then |
| 373 | add_subtree( ndntlv_info, { f_data_content, _payload, _payload:string() .. type_size_info } ) |
| 374 | end |
| 375 | elseif ( _type_uint == 22 ) then |
| 376 | -- SignatureInfo |
| 377 | if ( is_original ) then |
| 378 | child_tree = add_subtree( ndntlv_info, { f_data_signatureinfo, _payload, type_size_info } ) |
| 379 | end |
| 380 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 381 | elseif ( _type_uint == 23 ) then |
| 382 | -- SignatureValue |
| 383 | if ( is_original ) then |
| 384 | add_subtree( ndntlv_info, { f_data_signaturevalue, _payload, _payload:string() .. type_size_info } ) |
| 385 | end |
| 386 | elseif ( _type_uint == 24 ) then |
| 387 | -- MetaInfo / ContentType |
| 388 | if ( is_original ) then |
| 389 | add_subtree( ndntlv_info, { f_data_metainfo_contenttype, _payload, _payload:uint(), nil, type_size_info } ) |
| 390 | end |
| 391 | elseif ( _type_uint == 25 ) then |
| 392 | -- MetaInfo / FreshnessPeriod |
| 393 | if ( is_original ) then |
| 394 | add_subtree( ndntlv_info, { f_data_metainfo_freshnessperiod, _payload, _payload:uint(), nil, type_size_info } ) |
| 395 | end |
| 396 | elseif ( _type_uint == 26 ) then |
| 397 | -- MetaInfo / FinalBlockId |
| 398 | if ( is_original ) then |
| 399 | child_tree = add_subtree( ndntlv_info, { f_data_metainfo_finalblockid, _payload, type_size_info } ) |
| 400 | end |
| 401 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 402 | elseif ( _type_uint == 27 ) then |
| 403 | -- Signature / SignatureType |
| 404 | if ( is_original ) then |
| 405 | add_subtree( ndntlv_info, { f_data_signature_signaturetype, _payload, _payload:uint(), nil, type_size_info } ) |
| 406 | end |
| 407 | elseif ( _type_uint == 28 ) then |
| 408 | -- Signature / KeyLocator |
| 409 | if ( is_original ) then |
| 410 | child_tree = add_subtree( ndntlv_info, { f_data_signature_keylocator, _payload, type_size_info } ) |
| 411 | end |
| 412 | ret = ret and parse_ndn_tlv( packet_key, packet_number, is_original, _size_num, new_optional_params, child_tree ) |
| 413 | elseif ( _type_uint == 29 ) then |
| 414 | -- Signature / KeyDigest |
| 415 | if ( is_original ) then |
| 416 | add_subtree( ndntlv_info, { f_data_signature_keydigest, _payload, _payload:string() .. type_size_info } ); |
| 417 | end |
| 418 | else |
| 419 | --print("## warning ## unhandled type_uint: ", _type_uint) |
| 420 | ret = false |
| 421 | -- if the packet seems to be a NDN packet, it would be better idea to add some warning messages in the subtress instead of returning false. |
| 422 | end |
| 423 | end |
| 424 | return ret |
| 425 | end |
| 426 | |
| 427 | function create_subtree_from( info, subtree ) |
| 428 | for k, v in pairs( info["children"] ) do |
| 429 | local data = v["data"] |
| 430 | if type(data) == "table" then |
| 431 | local child_tree = subtree:add( unpack( data ) ) |
| 432 | create_subtree_from( v, child_tree ) |
| 433 | end |
| 434 | end |
| 435 | end |
| 436 | |
| 437 | function add_subtree( info, data ) |
| 438 | local child_tree = { ["data"] = data, ["children"] = {} } |
| 439 | table.insert( info["children"], child_tree ) |
| 440 | return child_tree |
| 441 | end |
| 442 | |
| 443 | function create_empty_ndntlv_info() |
| 444 | return { ["data"] = nil, ["children"] = {} } |
| 445 | end |
| 446 | |
| 447 | function parse_buffer_and_update( packet_key, packet_number, is_original, pkt, root, optional_params ) |
| 448 | -- TODO: need to set the maximum length |
| 449 | local ndntlv_info = create_empty_ndntlv_info() |
| 450 | local was_ndntlv_packet = parse_ndn_tlv( packet_key, packet_number, is_original, -1, optional_params, ndntlv_info ) |
| 451 | |
| 452 | if was_ndntlv_packet then |
| 453 | local buf = nil |
| 454 | if ( is_original ) then |
| 455 | buf = optional_params["buf"] |
| 456 | set_packet_status( packet_key, packet_number, "ndntlv_info", ndntlv_info ) |
| 457 | set_packet_status( packet_key, packet_number, "status", CONST_STR_NDNTLV ) |
| 458 | else |
| 459 | buf = ByteArray.tvb( optional_params["raw_bytes"], optional_params["tvb_name"] ) |
| 460 | ndntlv_info = create_empty_ndntlv_info() |
| 461 | parse_ndn_tlv( packet_key, packet_number, true, -1, { ["buf"] = buf }, ndntlv_info ) |
| 462 | |
| 463 | local used_packet_numbers = optional_params["used_packet_numbers"] |
| 464 | |
| 465 | for k,v in pairs(used_packet_numbers) do |
| 466 | set_packet_status( packet_key, v, "ndntlv_info", ndntlv_info ) |
| 467 | set_packet_status( packet_key, v, "status", CONST_STR_NDNTLV ) |
| 468 | end |
| 469 | end |
| 470 | end |
| 471 | |
| 472 | -- print( packet_key .. "--" .. packet_number .. ".." .. tostring(was_ndntlv_packet) ) |
| 473 | |
| 474 | -- It needs to check whether the packet type is NDN-TLV. |
| 475 | local saved_ndntlv_info = get_packet_status( packet_key, packet_number, "ndntlv_info" ) |
| 476 | local parsed = get_packet_status( packet_key, packet_number, "parsed" ) |
| 477 | if saved_ndntlv_info ~= nil then |
| 478 | pkt.cols.protocol = p_ndnproto.name -- set the protocol name to NDN |
| 479 | if ( parsed ~= true ) then |
| 480 | set_packet_status( packet_key, packet_number, "parsed", true ) |
| 481 | local subtree = root:add( p_ndnproto, buf ) -- create subtree for ndnproto |
| 482 | create_subtree_from( saved_ndntlv_info, subtree ) |
| 483 | end |
| 484 | end |
| 485 | end |
| 486 | |
| 487 | -- # not efficient |
| 488 | -- # lua -- doesn't support the random access...? |
| 489 | function get_next_element( tbl, current_value ) |
| 490 | for k, v in pairs( tbl ) do |
| 491 | if ( v > current_value ) then |
| 492 | return v |
| 493 | end |
| 494 | end |
| 495 | return current_value |
| 496 | end |
| 497 | |
| 498 | -- # not efficient |
| 499 | function get_previous_element( tbl, current_value ) |
| 500 | local prev = current_value |
| 501 | for k, v in pairs( tbl ) do |
| 502 | if ( v < current_value ) then |
| 503 | prev = v |
| 504 | else |
| 505 | break |
| 506 | end |
| 507 | end |
| 508 | return prev |
| 509 | end |
| 510 | |
| 511 | -- ndnproto dissector function |
| 512 | function p_ndnproto.dissector( buf, pkt, root ) |
| 513 | -- validate packet length is adequate, otherwise quit |
| 514 | local length = buf:len() |
| 515 | local packet_number = pkt.number -- an unique serial for each packet |
| 516 | local packet_key = tostring(pkt.src) .. ":" .. tostring(pkt.src_port) .. ":" .. tostring(pkt.dst) .. ":" .. tostring(pkt.dst_port) |
| 517 | print("## info ## packet[" .. packet_number .. "], length = " .. length ) |
| 518 | set_packet_status( packet_key, packet_number, "parsed", false ) |
| 519 | |
| 520 | if length == 0 then |
| 521 | else |
| 522 | local raw_bytes = buf:range():bytes() |
| 523 | parse_buffer_and_update( packet_key, packet_number, true, pkt, root, { ["buf"] = buf } ) |
| 524 | set_packet_status( packet_key, packet_number, "buffer", raw_bytes ) |
| 525 | |
| 526 | local pending_packet_numbers = get_keys_from( pending_packets[ packet_key ] ) |
| 527 | for k, v in pairs( pending_packet_numbers ) do |
| 528 | local pending_packet_number = v |
| 529 | |
| 530 | if ( pending_packet_number <= packet_number ) then |
| 531 | |
| 532 | local status = get_packet_status( packet_key, pending_packet_number, "status" ) |
| 533 | local expected_size = get_packet_status( packet_key, pending_packet_number, "expected_size" ) |
| 534 | local used_packet_numbers = {} |
| 535 | |
| 536 | if ( status == CONST_STR_TRUNCATED ) then |
| 537 | local merged_temp_buf = ByteArray.new() |
| 538 | local temp_packet_number = pending_packet_number |
| 539 | local pending_packet_number_end = 0 |
| 540 | while (merged_temp_buf:len() < expected_size) do |
| 541 | local temp_buf = get_packet_status( packet_key, temp_packet_number, "buffer" ) |
| 542 | if ( temp_buf == nil ) then |
| 543 | break |
| 544 | else |
| 545 | merged_temp_buf:append( temp_buf ) |
| 546 | pending_packet_number_end = temp_packet_number |
| 547 | |
| 548 | table.insert( used_packet_numbers, temp_packet_number ) |
| 549 | temp_packet_number = get_next_element( pending_packet_numbers, temp_packet_number ) |
| 550 | end |
| 551 | end |
| 552 | if ( merged_temp_buf:len() >= expected_size ) then |
| 553 | local merged_tvb_name = "Reassembled (" .. pending_packet_number .. "-" .. pending_packet_number_end .. ")" |
| 554 | local merged_parser_option = { |
| 555 | ["raw_bytes"] = merged_temp_buf, |
| 556 | ["tvb_name"] = merged_tvb_name, |
| 557 | ["pending_packet_number"] = pending_packet_number, |
| 558 | ["pending_packet_number_end"] = pending_packet_number_end, |
| 559 | ["used_packet_numbers"] = used_packet_numbers, |
| 560 | } |
| 561 | print(pending_packet_number .. ".." .. pending_packet_number_end) |
| 562 | parse_buffer_and_update( packet_key, packet_number, false, pkt, root, merged_parser_option ) |
| 563 | end |
| 564 | end |
| 565 | end |
| 566 | end |
| 567 | --dump_packet_status() |
| 568 | end |
| 569 | end |
| 570 | |
| 571 | -- Initialization routine |
| 572 | function p_ndnproto.init() |
| 573 | end |
| 574 | |
| 575 | local websocket_dissector_table = DissectorTable.get("ws.port") |
| 576 | websocket_dissector_table:add("1-65535", p_ndnproto) |
| 577 | |
| 578 | local tcp_dissector_table = DissectorTable.get("tcp.port") |
| 579 | tcp_dissector_table:add("6363", p_ndnproto) |
| 580 | |
| 581 | local udp_dissector_table = DissectorTable.get("udp.port") |
| 582 | udp_dissector_table:add("6363", p_ndnproto) |
| 583 | |
| 584 | print("ndntlv.lua is successfully loaded.") |
| 585 | |
| 586 | ---------------------------------------------------------------------- |
| 587 | -- helper functions |
| 588 | ---------------------------------------------------------------------- |
| 589 | function dump_buf(buf) |
| 590 | print("buffer.length = "..buf:len()) |
| 591 | local tmp = "" |
| 592 | for i=0, buf:len()-1 do |
| 593 | if i % 16 == 0 then |
| 594 | tmp = tmp .. string.format("%04d",i) .. " : " |
| 595 | end |
| 596 | tmp = tmp .. (buf:range(i,1).." ") |
| 597 | if (i+1) % 16 == 0 then |
| 598 | tmp = tmp .. ("\n") |
| 599 | end |
| 600 | end |
| 601 | print(tmp) |
| 602 | end |
| 603 | |
| 604 | function print_table(tbl, indent) |
| 605 | if not indent then indent = 0 end |
| 606 | for k, v in pairs(tbl) do |
| 607 | formatting = string.rep(" ", indent) .. k .. ": " |
| 608 | if type(v) == "table" then |
| 609 | print(formatting) |
| 610 | print_table(v, indent+1) |
| 611 | elseif type(v) == 'boolean' then |
| 612 | print(formatting , tostring(v)) |
| 613 | else |
| 614 | print(formatting , v) |
| 615 | end |
| 616 | end |
| 617 | end |