summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt14
-rw-r--r--apps/CMakeLists.txt35
-rw-r--r--apps/cmake/Modules/Packaging.cmake8
-rw-r--r--apps/higet/CMakeLists.txt10
-rw-r--r--apps/hiperf/CMakeLists.txt44
-rw-r--r--apps/hiperf/src/client.cc900
-rw-r--r--apps/hiperf/src/client.h (renamed from libtransport/includes/hicn/transport/interfaces/rtc_socket_producer.h)24
-rw-r--r--apps/hiperf/src/common.h217
-rw-r--r--apps/hiperf/src/forwarder_config.h97
-rw-r--r--apps/hiperf/src/forwarder_interface.cc676
-rw-r--r--apps/hiperf/src/forwarder_interface.h131
-rw-r--r--apps/hiperf/src/main.cc456
-rw-r--r--apps/hiperf/src/server.cc516
-rw-r--r--apps/hiperf/src/server.h (renamed from libtransport/includes/hicn/transport/security/crypto_hash_type.h)25
-rw-r--r--apps/http-proxy/CMakeLists.txt12
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt2
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h16
-rw-r--r--apps/http-proxy/src/forwarder_interface.cc4
-rw-r--r--apps/http-proxy/src/http_proxy.cc66
-rw-r--r--apps/http-proxy/src/http_session.cc55
-rw-r--r--apps/http-proxy/src/icn_receiver.cc24
-rw-r--r--apps/ping/.clang-format (renamed from utils/.clang-format)0
-rw-r--r--apps/ping/CMakeLists.txt39
-rw-r--r--apps/ping/src/ping_client.cc (renamed from utils/src/ping_client.cc)18
-rw-r--r--apps/ping/src/ping_server.cc (renamed from utils/src/ping_server.cc)6
-rw-r--r--cmake/Modules/BuildMacros.cmake21
-rw-r--r--cmake/Modules/FindConfig.cmake56
-rw-r--r--cmake/Modules/FindLibFec.cmake24
-rw-r--r--cmake/Modules/FindLibRely.cmake24
-rw-r--r--cmake/Modules/FindLibconfig++.cmake1
-rw-r--r--cmake/Modules/Packager.cmake90
-rw-r--r--ctrl/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/CMakeLists.txt2
-rw-r--r--ctrl/libhicnctrl/CMakeLists.txt10
-rw-r--r--ctrl/libhicnctrl/cmake/Modules/Packaging.cmake59
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h35
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt50
-rw-r--r--ctrl/libhicnctrl/src/api.c2396
-rw-r--r--ctrl/libhicnctrl/src/api_private.h208
-rw-r--r--ctrl/libhicnctrl/src/cli.c27
-rw-r--r--ctrl/libhicnctrl/src/modules/CMakeLists.txt48
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_api.c2278
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_plugin_api.c (renamed from ctrl/libhicnctrl/src/hicn_plugin_api.c)678
-rw-r--r--ctrl/sysrepo-plugins/CMakeLists.txt2
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt1
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt1
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt2
-rw-r--r--extras/CMakeLists.txt2
-rw-r--r--extras/libmemif/CMakeLists.txt2
-rw-r--r--extras/libyang/CMakeLists.txt2
-rw-r--r--extras/router-plugin/CMakeLists.txt2
-rw-r--r--extras/sysrepo/CMakeLists.txt2
-rw-r--r--hicn-light/CMakeLists.txt19
-rw-r--r--hicn-light/src/hicn/command_line/controller/CMakeLists.txt7
-rw-r--r--hicn-light/src/hicn/command_line/daemon/CMakeLists.txt7
-rw-r--r--hicn-light/src/hicn/config/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/config/commandOps.c1
-rw-r--r--hicn-light/src/hicn/content_store/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/core/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/io/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/messenger/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/platforms/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/processor/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/socket/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/strategies/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/utils/CMakeLists.txt2
-rw-r--r--hicn-plugin/.clang-format1
-rw-r--r--hicn-plugin/CMakeLists.txt2
-rw-r--r--hicn-plugin/src/CMakeLists.txt5
-rw-r--r--hicn-plugin/src/cli.c28
-rw-r--r--hicn-plugin/vapi/CMakeLists.txt3
-rw-r--r--lib/.clang-format1
-rw-r--r--lib/CMakeLists.txt2
-rw-r--r--lib/includes/hicn/compat.h5
-rw-r--r--lib/includes/hicn/ops.h622
-rw-r--r--lib/includes/hicn/protocol/ah.h17
-rw-r--r--lib/src/CMakeLists.txt2
-rw-r--r--lib/src/compat.c23
-rw-r--r--lib/src/ops.c13
-rw-r--r--lib/src/protocol/ah.c86
-rw-r--r--lib/src/protocol/icmp.c251
-rw-r--r--lib/src/protocol/ipv4.c195
-rw-r--r--lib/src/protocol/ipv6.c184
-rw-r--r--lib/src/protocol/tcp.c211
-rw-r--r--libtransport/CMakeLists.txt57
-rw-r--r--libtransport/cmake/Modules/DefaultConfiguration.cmake2
-rw-r--r--libtransport/cmake/Modules/Ios.cmake3
-rw-r--r--libtransport/cmake/Modules/Packaging.cmake77
-rw-r--r--libtransport/includes/hicn/transport/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/auth/CMakeLists.txt4
-rw-r--r--libtransport/includes/hicn/transport/auth/common.h2
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_hash.h151
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_hash_type.h35
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_hasher.h70
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_suite.h39
-rw-r--r--libtransport/includes/hicn/transport/auth/identity.h23
-rw-r--r--libtransport/includes/hicn/transport/auth/signer.h69
-rw-r--r--libtransport/includes/hicn/transport/auth/verifier.h144
-rw-r--r--libtransport/includes/hicn/transport/core/CMakeLists.txt3
-rw-r--r--libtransport/includes/hicn/transport/core/asio_wrapper.h (renamed from libtransport/includes/hicn/transport/interfaces/verification_policy.h)25
-rw-r--r--libtransport/includes/hicn/transport/core/connector_stats.h13
-rw-r--r--libtransport/includes/hicn/transport/core/content_object.h8
-rw-r--r--libtransport/includes/hicn/transport/core/endpoint.h5
-rw-r--r--libtransport/includes/hicn/transport/core/global_object_pool.h4
-rw-r--r--libtransport/includes/hicn/transport/core/interest.h10
-rw-r--r--libtransport/includes/hicn/transport/core/io_module.h6
-rw-r--r--libtransport/includes/hicn/transport/core/packet.h40
-rw-r--r--libtransport/includes/hicn/transport/errors/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/http/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/callbacks.h2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/portal.h12
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_consumer.h8
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_producer.h8
-rw-r--r--libtransport/includes/hicn/transport/interfaces/statistics.h24
-rw-r--r--libtransport/includes/hicn/transport/portability/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/portability/c_portability.h8
-rw-r--r--libtransport/includes/hicn/transport/portability/portability.h43
-rw-r--r--libtransport/includes/hicn/transport/portability/win_portability.h1
-rw-r--r--libtransport/includes/hicn/transport/security/CMakeLists.txt27
-rw-r--r--libtransport/includes/hicn/transport/security/crypto_hash.h119
-rw-r--r--libtransport/includes/hicn/transport/security/crypto_hasher.h68
-rw-r--r--libtransport/includes/hicn/transport/security/crypto_suite.h36
-rw-r--r--libtransport/includes/hicn/transport/security/identity.h61
-rw-r--r--libtransport/includes/hicn/transport/security/signer.h85
-rw-r--r--libtransport/includes/hicn/transport/security/verifier.h94
-rw-r--r--libtransport/includes/hicn/transport/utils/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/utils/event_thread.h6
-rw-r--r--libtransport/includes/hicn/transport/utils/fixed_block_allocator.h21
-rw-r--r--libtransport/includes/hicn/transport/utils/linux.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/log.h1056
-rw-r--r--libtransport/includes/hicn/transport/utils/membuf.h4
-rw-r--r--libtransport/includes/hicn/transport/utils/move_wrapper.h3
-rw-r--r--libtransport/includes/hicn/transport/utils/object_pool.h3
-rw-r--r--libtransport/includes/hicn/transport/utils/singleton.h6
-rw-r--r--libtransport/src/CMakeLists.txt59
-rw-r--r--libtransport/src/auth/CMakeLists.txt4
-rw-r--r--libtransport/src/auth/crypto_hash.cc201
-rw-r--r--libtransport/src/auth/crypto_suite.cc81
-rw-r--r--libtransport/src/auth/identity.cc286
-rw-r--r--libtransport/src/auth/signer.cc277
-rw-r--r--libtransport/src/auth/verifier.cc427
-rw-r--r--libtransport/src/config.h.in1
-rw-r--r--libtransport/src/core/CMakeLists.txt5
-rw-r--r--libtransport/src/core/connector.cc51
-rw-r--r--libtransport/src/core/connector.h109
-rw-r--r--libtransport/src/core/content_object.cc13
-rw-r--r--libtransport/src/core/fec.cc880
-rw-r--r--libtransport/src/core/forwarder_interface.h149
-rw-r--r--libtransport/src/core/global_configuration.cc40
-rw-r--r--libtransport/src/core/hicn_forwarder_interface.cc135
-rw-r--r--libtransport/src/core/hicn_forwarder_interface.h86
-rw-r--r--libtransport/src/core/hicn_vapi.c235
-rw-r--r--libtransport/src/core/hicn_vapi.h88
-rw-r--r--libtransport/src/core/interest.cc16
-rw-r--r--libtransport/src/core/io_module.cc8
-rw-r--r--libtransport/src/core/local_connector.cc7
-rw-r--r--libtransport/src/core/local_connector.h6
-rw-r--r--libtransport/src/core/manifest_format.h2
-rw-r--r--libtransport/src/core/manifest_format_fixed.cc8
-rw-r--r--libtransport/src/core/manifest_inline.h16
-rw-r--r--libtransport/src/core/memif_connector.cc499
-rw-r--r--libtransport/src/core/memif_connector.h133
-rw-r--r--libtransport/src/core/memif_vapi.c133
-rw-r--r--libtransport/src/core/memif_vapi.h60
-rw-r--r--libtransport/src/core/packet.cc37
-rw-r--r--libtransport/src/core/pending_interest.h7
-rw-r--r--libtransport/src/core/portal.cc5
-rw-r--r--libtransport/src/core/portal.h52
-rw-r--r--libtransport/src/core/raw_socket_connector.cc203
-rw-r--r--libtransport/src/core/raw_socket_connector.h81
-rw-r--r--libtransport/src/core/raw_socket_interface.cc57
-rw-r--r--libtransport/src/core/raw_socket_interface.h62
-rw-r--r--libtransport/src/core/rs.cc370
-rw-r--r--libtransport/src/core/tcp_socket_connector.cc20
-rw-r--r--libtransport/src/core/tcp_socket_connector.h3
-rw-r--r--libtransport/src/core/udp_socket_connector.cc224
-rw-r--r--libtransport/src/core/udp_socket_connector.h85
-rw-r--r--libtransport/src/core/vpp_forwarder_interface.cc226
-rw-r--r--libtransport/src/core/vpp_forwarder_interface.h88
-rw-r--r--libtransport/src/http/CMakeLists.txt2
-rw-r--r--libtransport/src/http/client_connection.cc23
-rw-r--r--libtransport/src/implementation/CMakeLists.txt2
-rw-r--r--libtransport/src/implementation/p2psecure_socket_consumer.cc6
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.cc23
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.h2
-rw-r--r--libtransport/src/implementation/rtc_socket_producer.cc352
-rw-r--r--libtransport/src/implementation/rtc_socket_producer.h74
-rw-r--r--libtransport/src/implementation/socket_consumer.h4
-rw-r--r--libtransport/src/implementation/socket_producer.h4
-rw-r--r--libtransport/src/implementation/tls_rtc_socket_producer.cc2
-rw-r--r--libtransport/src/implementation/tls_socket_producer.cc11
-rw-r--r--libtransport/src/interfaces/CMakeLists.txt2
-rw-r--r--libtransport/src/interfaces/global_configuration.cc6
-rw-r--r--libtransport/src/interfaces/portal.cc2
-rw-r--r--libtransport/src/io_modules/CMakeLists.txt7
-rw-r--r--libtransport/src/io_modules/forwarder/CMakeLists.txt5
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder.cc31
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder_module.cc6
-rw-r--r--libtransport/src/io_modules/forwarder/global_id_counter.h23
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel.cc50
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel.h3
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc16
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel_listener.h3
-rw-r--r--libtransport/src/io_modules/loopback/CMakeLists.txt6
-rw-r--r--libtransport/src/io_modules/loopback/local_face.cc7
-rw-r--r--libtransport/src/io_modules/loopback/local_face.h3
-rw-r--r--libtransport/src/io_modules/loopback/loopback_module.cc6
-rw-r--r--libtransport/src/io_modules/memif/CMakeLists.txt4
-rw-r--r--libtransport/src/io_modules/memif/hicn_vapi.c1
-rw-r--r--libtransport/src/io_modules/memif/memif_connector.cc35
-rw-r--r--libtransport/src/io_modules/memif/memif_connector.h4
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.cc15
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_connector.cc5
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_connector.h3
-rw-r--r--libtransport/src/io_modules/udp/CMakeLists.txt28
-rw-r--r--libtransport/src/io_modules/udp/udp_socket_connector.cc10
-rw-r--r--libtransport/src/io_modules/udp/udp_socket_connector.h3
-rw-r--r--libtransport/src/protocols/CMakeLists.txt16
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.cc30
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.h10
-rw-r--r--libtransport/src/protocols/cbr.cc2
-rw-r--r--libtransport/src/protocols/cbr.h3
-rw-r--r--libtransport/src/protocols/data_processing_events.h3
-rw-r--r--libtransport/src/protocols/datagram_reassembly.cc13
-rw-r--r--libtransport/src/protocols/datagram_reassembly.h2
-rw-r--r--libtransport/src/protocols/errors.cc11
-rw-r--r--libtransport/src/protocols/errors.h4
-rw-r--r--libtransport/src/protocols/fec/CMakeLists.txt (renamed from libtransport/src/security/CMakeLists.txt)22
-rw-r--r--libtransport/src/protocols/fec/fec.cc838
-rw-r--r--libtransport/src/protocols/fec/fec.h (renamed from libtransport/src/core/fec.h)14
-rw-r--r--libtransport/src/protocols/fec/fec_info.h62
-rw-r--r--libtransport/src/protocols/fec/rely.cc205
-rw-r--r--libtransport/src/protocols/fec/rely.h191
-rw-r--r--libtransport/src/protocols/fec/rs.cc418
-rw-r--r--libtransport/src/protocols/fec/rs.h (renamed from libtransport/src/core/rs.h)121
-rw-r--r--libtransport/src/protocols/fec_base.cc (renamed from libtransport/src/interfaces/rtc_socket_producer.cc)19
-rw-r--r--libtransport/src/protocols/fec_base.h85
-rw-r--r--libtransport/src/protocols/fec_utils.h155
-rw-r--r--libtransport/src/protocols/incremental_indexer.h138
-rw-r--r--libtransport/src/protocols/incremental_indexer_bytestream.cc (renamed from libtransport/src/protocols/incremental_indexer.cc)23
-rw-r--r--libtransport/src/protocols/incremental_indexer_bytestream.h119
-rw-r--r--libtransport/src/protocols/index_manager_bytestream.cc72
-rw-r--r--libtransport/src/protocols/index_manager_bytestream.h91
-rw-r--r--libtransport/src/protocols/indexer.cc60
-rw-r--r--libtransport/src/protocols/indexer.h91
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc (renamed from libtransport/src/protocols/manifest_incremental_indexer.cc)95
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer_bytestream.h (renamed from libtransport/src/protocols/manifest_incremental_indexer.h)27
-rw-r--r--libtransport/src/protocols/packet_manager.h65
-rw-r--r--libtransport/src/protocols/prod_protocol_bytestream.cc74
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.cc230
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.h27
-rw-r--r--libtransport/src/protocols/production_protocol.cc7
-rw-r--r--libtransport/src/protocols/production_protocol.h29
-rw-r--r--libtransport/src/protocols/protocol.cc137
-rw-r--r--libtransport/src/protocols/protocol.h114
-rw-r--r--libtransport/src/protocols/raaqm.cc180
-rw-r--r--libtransport/src/protocols/raaqm.h38
-rw-r--r--libtransport/src/protocols/rate_estimation.cc6
-rw-r--r--libtransport/src/protocols/reassembly.cc2
-rw-r--r--libtransport/src/protocols/reassembly.h33
-rw-r--r--libtransport/src/protocols/rtc.cc984
-rw-r--r--libtransport/src/protocols/rtc.h228
-rw-r--r--libtransport/src/protocols/rtc/CMakeLists.txt20
-rw-r--r--libtransport/src/protocols/rtc/congestion_detection.cc101
-rw-r--r--libtransport/src/protocols/rtc/congestion_detection.h138
-rw-r--r--libtransport/src/protocols/rtc/probe_handler.cc2
-rw-r--r--libtransport/src/protocols/rtc/probe_handler.h10
-rw-r--r--libtransport/src/protocols/rtc/rtc.cc466
-rw-r--r--libtransport/src/protocols/rtc/rtc.h46
-rw-r--r--libtransport/src/protocols/rtc/rtc_consts.h35
-rw-r--r--libtransport/src/protocols/rtc/rtc_data_path.cc6
-rw-r--r--libtransport/src/protocols/rtc/rtc_indexer.h195
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.cc212
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.h26
-rw-r--r--libtransport/src/protocols/rtc/rtc_packet.h2
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_frame.cc79
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_frame.h46
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_queue.cc6
-rw-r--r--libtransport/src/protocols/rtc/rtc_reassembly.h46
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.cc152
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.h62
-rw-r--r--libtransport/src/protocols/rtc/trendline_estimator.cc334
-rw-r--r--libtransport/src/protocols/rtc/trendline_estimator.h147
-rw-r--r--libtransport/src/protocols/rtc_data_path.cc156
-rw-r--r--libtransport/src/protocols/rtc_data_path.h80
-rw-r--r--libtransport/src/protocols/transport_protocol.cc102
-rw-r--r--libtransport/src/protocols/transport_protocol.h74
-rw-r--r--libtransport/src/protocols/verification_manager.cc101
-rw-r--r--libtransport/src/protocols/verification_manager.h71
-rw-r--r--libtransport/src/security/identity.cc115
-rw-r--r--libtransport/src/security/signer.cc185
-rw-r--r--libtransport/src/security/verifier.cc251
-rw-r--r--libtransport/src/test/CMakeLists.txt55
-rw-r--r--libtransport/src/test/fec_reed_solomon.cc154
-rw-r--r--libtransport/src/test/fec_rely.cc156
-rw-r--r--libtransport/src/test/main.cc (renamed from libtransport/includes/hicn/transport/security/key_id.h)17
-rw-r--r--libtransport/src/test/test_auth.cc162
-rw-r--r--libtransport/src/test/test_consumer_producer_rtc.cc15
-rw-r--r--libtransport/src/test/test_core_manifest.cc19
-rw-r--r--libtransport/src/test/test_event_thread.cc11
-rw-r--r--libtransport/src/test/test_fec_reedsolomon.cc184
-rw-r--r--libtransport/src/test/test_fec_rely_wrapper.cc232
-rw-r--r--libtransport/src/test/test_indexer.cc322
-rw-r--r--libtransport/src/test/test_interest.cc5
-rw-r--r--libtransport/src/test/test_packet.cc9
-rw-r--r--libtransport/src/test/test_transport_producer.cc66
-rw-r--r--libtransport/src/transport.config52
-rw-r--r--libtransport/src/utils/CMakeLists.txt2
-rw-r--r--libtransport/src/utils/content_store.cc20
-rw-r--r--libtransport/src/utils/content_store.h4
-rw-r--r--libtransport/src/utils/daemonizator.cc4
-rw-r--r--libtransport/src/utils/epoll_event_reactor.cc25
-rw-r--r--libtransport/src/utils/fd_deadline_timer.h3
-rw-r--r--libtransport/src/utils/log.cc1450
-rw-r--r--libtransport/src/utils/min_filter.h11
-rw-r--r--libtransport/src/utils/suffix_strategy.h31
-rw-r--r--libtransport/third-party/CMakeLists.txt83
-rw-r--r--libtransport/third-party/CMakeLists.txt.orig85
-rw-r--r--libtransport/third-party/CMakeLists.txt.rej21
-rw-r--r--libtransport/third-party/glog.patch23
-rw-r--r--telemetry/CMakeLists.txt2
-rw-r--r--telemetry/vpp-collectd/CMakeLists.txt2
-rw-r--r--telemetry/vpp-collectd/cmake/Modules/Packaging.cmake2
-rw-r--r--telemetry/vpp-collectd/common/README.md12
-rw-r--r--telemetry/vpp-collectd/common/common.h405
-rw-r--r--telemetry/vpp-collectd/common/meta_data.h71
-rw-r--r--telemetry/vpp-collectd/common/plugin.h485
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt5
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c19
-rw-r--r--telemetry/vpp-collectd/vpp/CMakeLists.txt5
-rw-r--r--telemetry/vpp-collectd/vpp/vpp.c19
-rw-r--r--utils/CMakeLists.txt98
-rw-r--r--utils/cmake/Modules/Packaging.cmake28
-rw-r--r--utils/src/hiperf.cc1683
336 files changed, 15417 insertions, 18950 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 31f40aaa6..8ad59c81d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(hicn-fdio)
@@ -23,8 +23,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
option(BUILD_LIBHICN "Build the hicn core library" ON)
option(BUILD_HICNLIGHT "Build the hicn light forwarder" ON)
option(BUILD_LIBTRANSPORT "Build the hicn transport library" ON)
-option(BUILD_UTILS "Build the hicn utils" ON)
-option(BUILD_APPS "Build the hicn apps" OFF)
+option(BUILD_APPS "Build the hicn apps" ON)
if (NOT WIN32)
option(BUILD_CTRL "Build the hicn control tools" ON)
option(DISABLE_SHARED_LIBRARIES "Disable shared libraries" OFF)
@@ -39,7 +38,7 @@ option(BUILD_TELEMETRY "Build telemetry projects" OFF)
option(BUILD_TESTS "Build unit tests" OFF)
option(DISABLE_EXECUTABLES "Disable executables" OFF)
-if ((BUILD_APPS OR BUILD_UTILS) AND NOT BUILD_LIBTRANSPORT)
+if (BUILD_APPS AND NOT BUILD_LIBTRANSPORT)
message(STATUS "Libhicntransport required. Enabled by default.")
set (BUILD_LIBTRANSPORT ON)
endif()
@@ -51,7 +50,6 @@ endif()
if ((BUILD_HICNLIGHT OR
BUILD_LIBTRANSPORT OR
- BUILD_UTILS OR
BUILD_APPS OR
BUILD_CTRL OR
BUILD_HICNPLUGIN OR
@@ -67,7 +65,6 @@ list(APPEND dir_options
BUILD_HICNPLUGIN
BUILD_CTRL
BUILD_LIBTRANSPORT
- BUILD_UTILS
BUILD_APPS
BUILD_SYSREPOPLUGIN
BUILD_EXTRAS
@@ -77,7 +74,6 @@ list(APPEND dir_options
set(BUILD_LIBHICN_DIR lib)
set(BUILD_HICNLIGHT_DIR hicn-light)
set(BUILD_LIBTRANSPORT_DIR libtransport)
-set(BUILD_UTILS_DIR utils)
set(BUILD_APPS_DIR apps)
set(BUILD_CTRL_DIR ctrl)
set(BUILD_HICNPLUGIN_DIR hicn-plugin)
@@ -94,10 +90,6 @@ foreach (opt ${dir_options})
endif()
endforeach()
-if (NOT WIN32)
- add_compile_options(-Wall -Werror -Wno-shorten-64-to-32)
-endif ()
-
# Add unit tests
if (BUILD_TESTS)
message(STATUS "Tests enabled.")
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 37e44f9e7..df1b9fc7c 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 14)
project(apps)
@@ -22,25 +22,32 @@ set(CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
+if (NOT CMAKE_BUILD_TYPE)
+ message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
+ set(CMAKE_BUILD_TYPE "Release")
+endif ()
+
include(BuildMacros)
include(WindowsMacros)
set(HICN_APPS hicn-apps CACHE INTERNAL "" FORCE)
+find_package(Threads REQUIRED)
+find_package(Libconfig++ REQUIRED)
+
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
find_package(Libtransport REQUIRED)
+ find_package(Libhicn REQUIRED)
find_package(hicnctrl REQUIRED)
- find_package(Threads REQUIRED)
else()
if (DISABLE_SHARED_LIBRARIES)
find_package(OpenSSL REQUIRED)
- if (NOT WIN32)
- find_package(ZLIB REQUIRED)
- endif ()
set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC})
+ set(LIBHICN_LIBRARIES ${LIBHICN_STATIC})
set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC})
else ()
set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_SHARED})
+ set(LIBHICN_LIBRARIES ${LIBHICN_SHARED})
set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_SHARED})
endif ()
@@ -49,28 +56,20 @@ else()
)
endif()
-# Worksroung for unresolved symbols in vpp libraries
-if(${CMAKE_SYSTEM_NAME} MATCHES Linux)
- set(LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs")
-endif()
-
-list(APPEND LIBRARIES
- ${LIBTRANSPORT_LIBRARIES}
- ${LIBHICNCTRL_LIBRARIES}
- ${OPENSSL_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
-)
-
-set(APPS_LIBRARY_LIST "${OPENSSL_LIBRARIES};${CMAKE_THREAD_LIBS_INIT}" CACHE INTERNAL "APPS_LIBRARY_LIST")
if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 /wd4996")
endif ()
include(Packaging)
+add_subdirectory(ping)
+add_subdirectory(hiperf)
+
set(HIGET higet)
set(HTTP_PROXY hicn-http-proxy)
+
if (NOT WIN32)
add_subdirectory(http-proxy)
endif ()
+
add_subdirectory(higet)
diff --git a/apps/cmake/Modules/Packaging.cmake b/apps/cmake/Modules/Packaging.cmake
index 9b3fa2e72..981eb728e 100644
--- a/apps/cmake/Modules/Packaging.cmake
+++ b/apps/cmake/Modules/Packaging.cmake
@@ -18,21 +18,21 @@ useful for testing and debugging within a hicn network."
)
set(${HICN_APPS}_DEB_DEPENDENCIES
- "lib${LIBTRANSPORT} (>= stable_version)"
+ "lib${LIBTRANSPORT} (>= stable_version), lib${LIBHICNCTRL} (>= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${HICN_APPS}-dev_DEB_DEPENDENCIES
- "lib${LIBTRANSPORT}-dev (>= stable_version)"
+ "${HICN_APPS} (>= stable_version), lib${LIBTRANSPORT}-dev (>= stable_version), lib${LIBHICNCTRL}-dev (>= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${HICN_APPS}_RPM_DEPENDENCIES
- "lib${LIBTRANSPORT} >= stable_version"
+ "lib${LIBTRANSPORT} >= stable_version, lib${LIBHICNCTRL} >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${HICN_APPS}-dev_RPM_DEPENDENCIES
- "lib${LIBTRANSPORT}-devel >= stable_version"
+ "${HICN_APPS} >= stable_version, lib${LIBTRANSPORT}-dev >= stable_version, lib${LIBHICNCTRL}-dev >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
) \ No newline at end of file
diff --git a/apps/higet/CMakeLists.txt b/apps/higet/CMakeLists.txt
index b929a24e4..8d112d3a3 100644
--- a/apps/higet/CMakeLists.txt
+++ b/apps/higet/CMakeLists.txt
@@ -11,11 +11,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 14)
project(utils)
+find_package(Threads REQUIRED)
+
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
@@ -38,7 +40,11 @@ endif()
if (NOT DISABLE_EXECUTABLES)
build_executable(${HIGET}
SOURCES ${APPS_SRC}
- LINK_LIBRARIES ${LIBTRANSPORT_LIBRARIES} ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
+ LINK_LIBRARIES
+ ${LIBTRANSPORT_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${WSOCK32_LIBRARY}
+ ${WS2_32_LIBRARY}
DEPENDS ${LIBTRANSPORT_LIBRARIES}
COMPONENT ${HICN_APPS}
DEFINITIONS ${COMPILER_DEFINITIONS}
diff --git a/apps/hiperf/CMakeLists.txt b/apps/hiperf/CMakeLists.txt
new file mode 100644
index 000000000..564525e67
--- /dev/null
+++ b/apps/hiperf/CMakeLists.txt
@@ -0,0 +1,44 @@
+# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if (NOT DISABLE_EXECUTABLES)
+ list(APPEND HIPERF_SRC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/client.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/server.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/forwarder_interface.cc
+ )
+
+ list (APPEND HIPERF_LIBRARIES
+ ${LIBTRANSPORT_LIBRARIES}
+ ${LIBHICNCTRL_LIBRARIES}
+ ${LIBHICN_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${LIBCONFIG_CPP_LIBRARIES}
+ ${WSOCK32_LIBRARY}
+ ${WS2_32_LIBRARY}
+ )
+
+ build_executable(hiperf
+ SOURCES ${HIPERF_SRC}
+ LINK_LIBRARIES ${HIPERF_LIBRARIES}
+ INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${LIBTRANSPORT_INCLUDE_DIRS}
+ ${LIBHICNCTRL_INCLUDE_DIRS}
+ ${LIBCONFIG_CPP_INCLUDE_DIRS}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${HICN_APPS}
+ LINK_FLAGS ${LINK_FLAGS}
+ )
+endif() \ No newline at end of file
diff --git a/apps/hiperf/src/client.cc b/apps/hiperf/src/client.cc
new file mode 100644
index 000000000..820ebf0ce
--- /dev/null
+++ b/apps/hiperf/src/client.cc
@@ -0,0 +1,900 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <client.h>
+#include <forwarder_config.h>
+#include <forwarder_interface.h>
+
+#include <libconfig.h++>
+
+namespace hiperf {
+
+/**
+ * Forward declaration of client Read callbacks.
+ */
+class RTCCallback;
+class Callback;
+
+/**
+ * Hiperf client class: configure and setup an hicn consumer following the
+ * ClientConfiguration.
+ */
+class HIperfClient::Impl
+#ifdef FORWARDER_INTERFACE
+ : ForwarderInterface::ICallback
+#endif
+{
+ typedef std::chrono::time_point<std::chrono::steady_clock> Time;
+ typedef std::chrono::microseconds TimeDuration;
+
+ friend class Callback;
+ friend class RTCCallback;
+
+ struct nack_packet_t {
+ uint64_t timestamp;
+ uint32_t prod_rate;
+ uint32_t prod_seg;
+
+ inline uint64_t getTimestamp() const { return _ntohll(&timestamp); }
+ inline void setTimestamp(uint64_t time) { timestamp = _htonll(&time); }
+
+ inline uint32_t getProductionRate() const { return ntohl(prod_rate); }
+ inline void setProductionRate(uint32_t rate) { prod_rate = htonl(rate); }
+
+ inline uint32_t getProductionSegement() const { return ntohl(prod_seg); }
+ inline void setProductionSegement(uint32_t seg) { prod_seg = htonl(seg); }
+ };
+
+ public:
+ Impl(const hiperf::ClientConfiguration &conf)
+ : configuration_(conf),
+ total_duration_milliseconds_(0),
+ old_bytes_value_(0),
+ old_interest_tx_value_(0),
+ old_fec_interest_tx_value_(0),
+ old_fec_data_rx_value_(0),
+ old_lost_data_value_(0),
+ old_bytes_recovered_value_(0),
+ old_definitely_lost_data_value_(0),
+ old_retx_value_(0),
+ old_sent_int_value_(0),
+ old_received_nacks_value_(0),
+ old_fec_pkt_(0),
+ avg_data_delay_(0),
+ delay_sample_(0),
+ received_bytes_(0),
+ received_data_pkt_(0),
+ data_delays_(""),
+ signals_(io_service_),
+ rtc_callback_(*this),
+ callback_(*this),
+ socket_(io_service_),
+ done_(false),
+ switch_threshold_(~0)
+#ifdef FORWARDER_INTERFACE
+ ,
+ forwarder_interface_(io_service_, this)
+#endif
+ {
+ }
+
+ ~Impl() {}
+
+ void checkReceivedRtcContent(ConsumerSocket &c,
+ const ContentObject &contentObject) {}
+
+ void processLeavingInterest(ConsumerSocket &c, const Interest &interest) {}
+
+ void addFace(const std::string &local_address, uint16_t local_port,
+ const std::string &remote_address, uint16_t remote_port,
+ std::string interface);
+
+ void handleTimerExpiration(ConsumerSocket &c,
+ const TransportStatistics &stats) {
+ const char separator = ' ';
+ const int width = 15;
+
+ utils::TimePoint t2 = utils::SteadyClock::now();
+ auto exact_duration =
+ std::chrono::duration_cast<utils::Milliseconds>(t2 - t_stats_);
+
+ std::stringstream interval;
+ interval << total_duration_milliseconds_ / 1000 << "-"
+ << total_duration_milliseconds_ / 1000 +
+ exact_duration.count() / 1000;
+
+ std::stringstream bytes_transferred;
+ bytes_transferred << std::fixed << std::setprecision(3)
+ << (stats.getBytesRecv() - old_bytes_value_) / 1000000.0
+ << std::setfill(separator) << "[MB]";
+
+ std::stringstream bandwidth;
+ bandwidth << ((stats.getBytesRecv() - old_bytes_value_) * 8) /
+ (exact_duration.count()) / 1000.0
+ << std::setfill(separator) << "[Mbps]";
+
+ std::stringstream window;
+ window << stats.getAverageWindowSize() << std::setfill(separator)
+ << "[Int]";
+
+ std::stringstream avg_rtt;
+ avg_rtt << stats.getAverageRtt() << std::setfill(separator) << "[ms]";
+
+ if (configuration_.rtc_) {
+ // we get rtc stats more often, thus we need ms in the interval
+ std::stringstream interval_ms;
+ interval_ms << total_duration_milliseconds_ << "-"
+ << total_duration_milliseconds_ + exact_duration.count();
+
+ std::stringstream lost_data;
+ lost_data << stats.getLostData() - old_lost_data_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream bytes_recovered_data;
+ bytes_recovered_data << stats.getBytesRecoveredData() -
+ old_bytes_recovered_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream definitely_lost_data;
+ definitely_lost_data << stats.getDefinitelyLostData() -
+ old_definitely_lost_data_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream data_delay;
+ data_delay << avg_data_delay_ << std::setfill(separator) << "[ms]";
+
+ std::stringstream received_data_pkt;
+ received_data_pkt << received_data_pkt_ << std::setfill(separator)
+ << "[pkt]";
+
+ std::stringstream goodput;
+ goodput << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0
+ << std::setfill(separator) << "[Mbps]";
+
+ std::stringstream loss_rate;
+ loss_rate << std::fixed << std::setprecision(2)
+ << stats.getLossRatio() * 100.0 << std::setfill(separator)
+ << "[%]";
+
+ std::stringstream retx_sent;
+ retx_sent << stats.getRetxCount() - old_retx_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream interest_sent;
+ interest_sent << stats.getInterestTx() - old_sent_int_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream nacks;
+ nacks << stats.getReceivedNacks() - old_received_nacks_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream fec_pkt;
+ fec_pkt << stats.getReceivedFEC() - old_fec_pkt_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream queuing_delay;
+ queuing_delay << stats.getQueuingDelay() << std::setfill(separator)
+ << "[ms]";
+
+#ifdef FORWARDER_INTERFACE
+ if (!done_ && stats.getQueuingDelay() >= switch_threshold_ &&
+ total_duration_milliseconds_ > 1000) {
+ std::cout << "Switching due to queuing delay" << std::endl;
+ forwarder_interface_.createFaceAndRoutes(backup_routes_);
+ forwarder_interface_.deleteFaceAndRoutes(main_routes_);
+ std::swap(backup_routes_, main_routes_);
+ done_ = true;
+ }
+#endif
+
+ // statistics not yet available in the transport
+ // std::stringstream interest_fec_tx;
+ // interest_fec_tx << stats.getInterestFecTxCount() -
+ // old_fec_interest_tx_value_ << std::setfill(separator) << "[pkt]";
+ // std::stringstream bytes_fec_recv;
+ // bytes_fec_recv << stats.getBytesFecRecv() - old_fec_data_rx_value_
+ // << std::setfill(separator) << "[bytes]";
+ std::cout << std::left << std::setw(width) << "Interval";
+ std::cout << std::left << std::setw(width) << "RecvData";
+ std::cout << std::left << std::setw(width) << "Bandwidth";
+ std::cout << std::left << std::setw(width) << "Goodput";
+ std::cout << std::left << std::setw(width) << "LossRate";
+ std::cout << std::left << std::setw(width) << "Retr";
+ std::cout << std::left << std::setw(width) << "InterestSent";
+ std::cout << std::left << std::setw(width) << "ReceivedNacks";
+ std::cout << std::left << std::setw(width) << "SyncWnd";
+ std::cout << std::left << std::setw(width) << "MinRtt";
+ std::cout << std::left << std::setw(width) << "QueuingDelay";
+ std::cout << std::left << std::setw(width) << "LostData";
+ std::cout << std::left << std::setw(width) << "RecoveredData";
+ std::cout << std::left << std::setw(width) << "DefinitelyLost";
+ std::cout << std::left << std::setw(width) << "State";
+ std::cout << std::left << std::setw(width) << "DataDelay";
+ std::cout << std::left << std::setw(width) << "FecPkt" << std::endl;
+
+ std::cout << std::left << std::setw(width) << interval_ms.str();
+ std::cout << std::left << std::setw(width) << received_data_pkt.str();
+ std::cout << std::left << std::setw(width) << bandwidth.str();
+ std::cout << std::left << std::setw(width) << goodput.str();
+ std::cout << std::left << std::setw(width) << loss_rate.str();
+ std::cout << std::left << std::setw(width) << retx_sent.str();
+ std::cout << std::left << std::setw(width) << interest_sent.str();
+ std::cout << std::left << std::setw(width) << nacks.str();
+ std::cout << std::left << std::setw(width) << window.str();
+ std::cout << std::left << std::setw(width) << avg_rtt.str();
+ std::cout << std::left << std::setw(width) << queuing_delay.str();
+ std::cout << std::left << std::setw(width) << lost_data.str();
+ std::cout << std::left << std::setw(width) << bytes_recovered_data.str();
+ std::cout << std::left << std::setw(width) << definitely_lost_data.str();
+ std::cout << std::left << std::setw(width) << stats.getCCStatus();
+ std::cout << std::left << std::setw(width) << data_delay.str();
+ std::cout << std::left << std::setw(width) << fec_pkt.str();
+ std::cout << std::endl;
+
+ if (configuration_.test_mode_) {
+ if (data_delays_.size() > 0) data_delays_.pop_back();
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+ std::cout << now << " DATA-DELAYS:[" << data_delays_ << "]"
+ << std::endl;
+ }
+
+ // statistics not yet available in the transport
+ // std::cout << std::left << std::setw(width) << interest_fec_tx.str();
+ // std::cout << std::left << std::setw(width) << bytes_fec_recv.str();
+ } else {
+ std::cout << std::left << std::setw(width) << "Interval";
+ std::cout << std::left << std::setw(width) << "Transfer";
+ std::cout << std::left << std::setw(width) << "Bandwidth";
+ std::cout << std::left << std::setw(width) << "Retr";
+ std::cout << std::left << std::setw(width) << "Cwnd";
+ std::cout << std::left << std::setw(width) << "AvgRtt" << std::endl;
+
+ std::cout << std::left << std::setw(width) << interval.str();
+ std::cout << std::left << std::setw(width) << bytes_transferred.str();
+ std::cout << std::left << std::setw(width) << bandwidth.str();
+ std::cout << std::left << std::setw(width) << stats.getRetxCount();
+ std::cout << std::left << std::setw(width) << window.str();
+ std::cout << std::left << std::setw(width) << avg_rtt.str() << std::endl;
+ std::cout << std::endl;
+ }
+ total_duration_milliseconds_ += (uint32_t)exact_duration.count();
+ old_bytes_value_ = stats.getBytesRecv();
+ old_lost_data_value_ = stats.getLostData();
+ old_bytes_recovered_value_ = stats.getBytesRecoveredData();
+ old_definitely_lost_data_value_ = stats.getDefinitelyLostData();
+ old_fec_interest_tx_value_ = stats.getInterestFecTxCount();
+ old_fec_data_rx_value_ = stats.getBytesFecRecv();
+ old_retx_value_ = stats.getRetxCount();
+ old_sent_int_value_ = stats.getInterestTx();
+ old_received_nacks_value_ = stats.getReceivedNacks();
+ old_fec_pkt_ = stats.getReceivedFEC();
+ delay_sample_ = 0;
+ avg_data_delay_ = 0;
+ received_bytes_ = 0;
+ received_data_pkt_ = 0;
+ data_delays_ = "";
+
+ t_stats_ = utils::SteadyClock::now();
+ }
+
+ bool parseConfig(const char *conf_file) {
+ using namespace libconfig;
+ Config cfg;
+
+ try {
+ cfg.readFile(conf_file);
+ } catch (const FileIOException &fioex) {
+ std::cerr << "I/O error while reading file." << std::endl;
+ return false;
+ } catch (const ParseException &pex) {
+ std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
+ << " - " << pex.getError() << std::endl;
+ return false;
+ }
+
+ Setting &config = cfg.getRoot();
+
+ if (config.exists("switch_threshold")) {
+ unsigned threshold;
+ config.lookupValue("switch_threshold", threshold);
+ switch_threshold_ = threshold;
+ }
+
+ // listeners
+ if (config.exists("listeners")) {
+ // get path where looking for modules
+ const Setting &listeners = config.lookup("listeners");
+ auto count = listeners.getLength();
+
+ for (int i = 0; i < count; i++) {
+ const Setting &listener = listeners[i];
+ ListenerConfig list;
+ unsigned port;
+ std::string interface;
+
+ list.name = listener.getName();
+ listener.lookupValue("local_address", list.address);
+ listener.lookupValue("local_port", port);
+ listener.lookupValue("interface", list.interface);
+ list.port = (uint16_t)(port);
+
+ std::cout << "Adding listener " << list.name << ", ( " << list.address
+ << ":" << list.port << ")" << std::endl;
+ config_.addListener(std::move(list));
+ }
+ }
+
+ // connectors
+ if (config.exists("connectors")) {
+ // get path where looking for modules
+ const Setting &connectors = config.lookup("connectors");
+ auto count = connectors.getLength();
+
+ for (int i = 0; i < count; i++) {
+ const Setting &connector = connectors[i];
+ ConnectorConfig conn;
+
+ conn.name = connector.getName();
+ unsigned port = 0;
+
+ if (!connector.lookupValue("local_address", conn.local_address)) {
+ conn.local_address = "";
+ }
+
+ if (!connector.lookupValue("local_port", port)) {
+ port = 0;
+ }
+
+ conn.local_port = (uint16_t)(port);
+
+ if (!connector.lookupValue("remote_address", conn.remote_address)) {
+ std::cerr
+ << "Error in configuration file: remote_address is a mandatory "
+ "field of Connectors."
+ << std::endl;
+ return false;
+ }
+
+ if (!connector.lookupValue("remote_port", port)) {
+ std::cerr << "Error in configuration file: remote_port is a "
+ "mandatory field of Connectors."
+ << std::endl;
+ return false;
+ }
+
+ if (!connector.lookupValue("interface", conn.interface)) {
+ std::cerr << "Error in configuration file: interface is a "
+ "mandatory field of Connectors."
+ << std::endl;
+ return false;
+ }
+
+ conn.remote_port = (uint16_t)(port);
+
+ std::cout << "Adding connector " << conn.name << ", ("
+ << conn.local_address << ":" << conn.local_port << " "
+ << conn.remote_address << ":" << conn.remote_port << ")"
+ << std::endl;
+ config_.addConnector(conn.name, std::move(conn));
+ }
+ }
+
+ // Routes
+ if (config.exists("routes")) {
+ const Setting &routes = config.lookup("routes");
+ auto count = routes.getLength();
+
+ for (int i = 0; i < count; i++) {
+ const Setting &route = routes[i];
+ RouteConfig r;
+ unsigned weight;
+
+ r.name = route.getName();
+ route.lookupValue("prefix", r.prefix);
+ route.lookupValue("weight", weight);
+ route.lookupValue("main_connector", r.main_connector);
+ route.lookupValue("backup_connector", r.backup_connector);
+ r.weight = (uint16_t)(weight);
+
+ std::cout << "Adding route " << r.name << " " << r.prefix << " ("
+ << r.main_connector << " " << r.backup_connector << " "
+ << r.weight << ")" << std::endl;
+ config_.addRoute(std::move(r));
+ }
+ }
+
+ std::cout << "Ok" << std::endl;
+
+ return true;
+ }
+
+ bool splitRoute(std::string route, std::string &prefix,
+ uint8_t &prefix_length) {
+ std::string delimiter = "/";
+
+ size_t pos = 0;
+ if ((pos = route.find(delimiter)) != std::string::npos) {
+ prefix = route.substr(0, pos);
+ route.erase(0, pos + delimiter.length());
+ } else {
+ return false;
+ }
+
+ prefix_length = std::stoul(route.substr(0));
+ return true;
+ }
+
+#ifdef FORWARDER_INTERFACE
+ void onHicnServiceReady() override {
+ std::cout << "Successfully connected to local forwarder!" << std::endl;
+
+ std::cout << "Setting up listeners" << std::endl;
+ const char *config = getenv("FORWARDER_CONFIG");
+
+ if (config) {
+ if (!parseConfig(config)) {
+ return;
+ }
+
+ // Create faces and route using first face in the list.
+ auto &routes = config_.getRoutes();
+ auto &connectors = config_.getConnectors();
+
+ if (routes.size() == 0 || connectors.size() == 0) {
+ std::cerr << "Nothing to configure" << std::endl;
+ return;
+ }
+
+ for (auto &route : routes) {
+ auto the_connector_it = connectors.find(route.main_connector);
+ if (the_connector_it == connectors.end()) {
+ std::cerr << "No valid main connector found for route " << route.name
+ << std::endl;
+ continue;
+ }
+
+ auto &the_connector = the_connector_it->second;
+ auto route_info = std::make_shared<ForwarderInterface::RouteInfo>();
+ route_info->family = AF_INET;
+ route_info->local_addr = the_connector.local_address;
+ route_info->local_port = the_connector.local_port;
+ route_info->remote_addr = the_connector.remote_address;
+ route_info->remote_port = the_connector.remote_port;
+ route_info->interface = the_connector.interface;
+ route_info->name = the_connector.name;
+
+ std::string prefix;
+ uint8_t prefix_length;
+ auto ret = splitRoute(route.prefix, prefix, prefix_length);
+
+ if (!ret) {
+ std::cerr << "Error parsing route" << std::endl;
+ return;
+ }
+
+ route_info->route_addr = prefix;
+ route_info->route_len = prefix_length;
+
+ main_routes_.emplace_back(route_info);
+
+ if (!route.backup_connector.empty()) {
+ // Add also the backup route
+ auto the_backup_connector_it =
+ connectors.find(route.backup_connector);
+ if (the_backup_connector_it == connectors.end()) {
+ std::cerr << "No valid backup connector found for route "
+ << route.name << std::endl;
+ continue;
+ }
+
+ auto &the_backup_connector = the_backup_connector_it->second;
+ auto backup_route_info =
+ std::make_shared<ForwarderInterface::RouteInfo>();
+ backup_route_info->family = AF_INET;
+ backup_route_info->local_addr = the_backup_connector.local_address;
+ backup_route_info->local_port = the_backup_connector.local_port;
+ backup_route_info->remote_addr = the_backup_connector.remote_address;
+ backup_route_info->remote_port = the_backup_connector.remote_port;
+ backup_route_info->interface = the_backup_connector.interface;
+ backup_route_info->name = the_backup_connector.name;
+
+ std::string prefix;
+ uint8_t prefix_length;
+ auto ret = splitRoute(route.prefix, prefix, prefix_length);
+
+ if (!ret) {
+ std::cerr << "Error parsing route" << std::endl;
+ return;
+ }
+
+ backup_route_info->route_addr = prefix;
+ backup_route_info->route_len = prefix_length;
+
+ backup_routes_.emplace_back(backup_route_info);
+ }
+ }
+
+ // Create main routes
+ std::cout << "Creating main routes" << std::endl;
+ forwarder_interface_.createFaceAndRoutes(main_routes_);
+ }
+ }
+
+ void onRouteConfigured(
+ std::vector<ForwarderInterface::RouteInfoPtr> &route_info) override {
+ std::cout << "Routes successfully configured!" << std::endl;
+ }
+#endif
+
+ int setup() {
+ int ret;
+
+ if (configuration_.rtc_) {
+ configuration_.transport_protocol_ = RTC;
+ } else if (configuration_.window < 0) {
+ configuration_.transport_protocol_ = RAAQM;
+ } else {
+ configuration_.transport_protocol_ = CBR;
+ }
+
+ if (configuration_.relay_ && configuration_.rtc_) {
+ int production_protocol = ProductionProtocolAlgorithms::RTC_PROD;
+ producer_socket_ = std::make_unique<ProducerSocket>(production_protocol);
+ producer_socket_->registerPrefix(configuration_.relay_name_);
+ producer_socket_->connect();
+ }
+
+ if (configuration_.output_stream_mode_ && configuration_.rtc_) {
+ remote_ = asio::ip::udp::endpoint(
+ asio::ip::address::from_string("127.0.0.1"), configuration_.port_);
+ socket_.open(asio::ip::udp::v4());
+ }
+
+ if (configuration_.secure_) {
+ consumer_socket_ = std::make_unique<P2PSecureConsumerSocket>(
+ RAAQM, configuration_.transport_protocol_);
+ if (configuration_.producer_prefix_.getPrefixLength() == 0) {
+ std::cerr << "ERROR -- Missing producer prefix on which perform the "
+ "handshake."
+ << std::endl;
+ } else {
+ P2PSecureConsumerSocket &secure_consumer_socket =
+ *(static_cast<P2PSecureConsumerSocket *>(consumer_socket_.get()));
+ secure_consumer_socket.registerPrefix(configuration_.producer_prefix_);
+ }
+ } else {
+ consumer_socket_ =
+ std::make_unique<ConsumerSocket>(configuration_.transport_protocol_);
+ }
+
+ consumer_socket_->setSocketOption(
+ GeneralTransportOptions::INTEREST_LIFETIME,
+ configuration_.interest_lifetime_);
+
+#if defined(DEBUG) && defined(__linux__)
+ std::shared_ptr<transport::BasePortal> portal;
+ consumer_socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal);
+ signals_ =
+ std::make_unique<asio::signal_set>(portal->getIoService(), SIGUSR1);
+ signals_->async_wait([this](const std::error_code &, const int &) {
+ std::cout << "Signal SIGUSR1!" << std::endl;
+ mtrace();
+ });
+#endif
+
+ if (consumer_socket_->setSocketOption(CURRENT_WINDOW_SIZE,
+ configuration_.window) ==
+ SOCKET_OPTION_NOT_SET) {
+ std::cerr << "ERROR -- Impossible to set the size of the window."
+ << std::endl;
+ return ERROR_SETUP;
+ }
+
+ if (configuration_.transport_protocol_ == RAAQM &&
+ configuration_.beta != -1.f) {
+ if (consumer_socket_->setSocketOption(RaaqmTransportOptions::BETA_VALUE,
+ configuration_.beta) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ if (configuration_.transport_protocol_ == RAAQM &&
+ configuration_.drop_factor != -1.f) {
+ if (consumer_socket_->setSocketOption(RaaqmTransportOptions::DROP_FACTOR,
+ configuration_.drop_factor) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ if (!configuration_.producer_certificate.empty()) {
+ std::shared_ptr<Verifier> verifier = std::make_shared<AsymmetricVerifier>(
+ configuration_.producer_certificate);
+ if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
+ verifier) == SOCKET_OPTION_NOT_SET)
+ return ERROR_SETUP;
+ }
+
+ if (!configuration_.passphrase.empty()) {
+ std::shared_ptr<Verifier> verifier =
+ std::make_shared<SymmetricVerifier>(configuration_.passphrase);
+ if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
+ verifier) == SOCKET_OPTION_NOT_SET)
+ return ERROR_SETUP;
+ }
+
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::INTEREST_OUTPUT,
+ (ConsumerInterestCallback)std::bind(&Impl::processLeavingInterest, this,
+ std::placeholders::_1,
+ std::placeholders::_2));
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (!configuration_.rtc_) {
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::READ_CALLBACK, &callback_);
+ } else {
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::READ_CALLBACK, &rtc_callback_);
+ }
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (configuration_.rtc_) {
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
+ (ConsumerContentObjectCallback)std::bind(
+ &Impl::checkReceivedRtcContent, this, std::placeholders::_1,
+ std::placeholders::_2));
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ if (configuration_.rtc_) {
+ std::shared_ptr<TransportStatistics> transport_stats;
+ consumer_socket_->getSocketOption(
+ OtherOptions::STATISTICS, (TransportStatistics **)&transport_stats);
+ transport_stats->setAlpha(0.0);
+ }
+
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::STATS_SUMMARY,
+ (ConsumerTimerCallback)std::bind(&Impl::handleTimerExpiration, this,
+ std::placeholders::_1,
+ std::placeholders::_2));
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (consumer_socket_->setSocketOption(
+ GeneralTransportOptions::STATS_INTERVAL,
+ configuration_.report_interval_milliseconds_) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ consumer_socket_->connect();
+
+ return ERROR_SUCCESS;
+ }
+
+ int run() {
+ std::cout << "Starting download of " << configuration_.name << std::endl;
+
+ signals_.add(SIGINT);
+ signals_.async_wait(
+ [this](const std::error_code &, const int &) { io_service_.stop(); });
+
+ t_download_ = t_stats_ = std::chrono::steady_clock::now();
+ consumer_socket_->asyncConsume(configuration_.name);
+ io_service_.run();
+
+ consumer_socket_->stop();
+
+ return ERROR_SUCCESS;
+ }
+
+ private:
+ class RTCCallback : public ConsumerSocket::ReadCallback {
+ static constexpr std::size_t mtu = 1500;
+
+ public:
+ RTCCallback(Impl &hiperf_client) : client_(hiperf_client) {
+ client_.configuration_.receive_buffer = utils::MemBuf::create(mtu);
+ }
+
+ bool isBufferMovable() noexcept override { return false; }
+
+ void getReadBuffer(uint8_t **application_buffer,
+ size_t *max_length) override {
+ *application_buffer =
+ client_.configuration_.receive_buffer->writableData();
+ *max_length = mtu;
+ }
+
+ void readDataAvailable(std::size_t length) noexcept override {
+ client_.received_bytes_ += length;
+ client_.received_data_pkt_++;
+
+ // collecting delay stats. Just for performance testing
+ uint64_t *senderTimeStamp =
+ (uint64_t *)client_.configuration_.receive_buffer->writableData();
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+ double new_delay = (double)(now - *senderTimeStamp);
+
+ if (*senderTimeStamp > now)
+ new_delay = -1 * (double)(*senderTimeStamp - now);
+
+ client_.delay_sample_++;
+ client_.avg_data_delay_ =
+ client_.avg_data_delay_ +
+ (new_delay - client_.avg_data_delay_) / client_.delay_sample_;
+
+ if (client_.configuration_.test_mode_) {
+ client_.data_delays_ += std::to_string(int(new_delay));
+ client_.data_delays_ += ",";
+ }
+
+ if (client_.configuration_.relay_) {
+ client_.producer_socket_->produceDatagram(
+ client_.configuration_.relay_name_.getName(),
+ client_.configuration_.receive_buffer->writableData(),
+ length < 1400 ? length : 1400);
+ }
+ if (client_.configuration_.output_stream_mode_) {
+ uint8_t *start =
+ (uint8_t *)client_.configuration_.receive_buffer->writableData();
+ start += sizeof(uint64_t);
+ std::size_t pkt_len = length - sizeof(uint64_t);
+ client_.socket_.send_to(asio::buffer(start, pkt_len), client_.remote_);
+ }
+ }
+
+ size_t maxBufferSize() const override { return mtu; }
+
+ void readError(const std::error_code ec) noexcept override {
+ std::cerr << "Error while reading from RTC socket" << std::endl;
+ client_.io_service_.stop();
+ }
+
+ void readSuccess(std::size_t total_size) noexcept override {
+ std::cout << "Data successfully read" << std::endl;
+ }
+
+ private:
+ Impl &client_;
+ };
+
+ class Callback : public ConsumerSocket::ReadCallback {
+ public:
+ Callback(Impl &hiperf_client) : client_(hiperf_client) {
+ client_.configuration_.receive_buffer =
+ utils::MemBuf::create(client_.configuration_.receive_buffer_size_);
+ }
+
+ bool isBufferMovable() noexcept override { return false; }
+
+ void getReadBuffer(uint8_t **application_buffer,
+ size_t *max_length) override {
+ *application_buffer =
+ client_.configuration_.receive_buffer->writableData();
+ *max_length = client_.configuration_.receive_buffer_size_;
+ }
+
+ void readDataAvailable(std::size_t length) noexcept override {}
+
+ void readBufferAvailable(
+ std::unique_ptr<utils::MemBuf> &&buffer) noexcept override {}
+
+ size_t maxBufferSize() const override {
+ return client_.configuration_.receive_buffer_size_;
+ }
+
+ void readError(const std::error_code ec) noexcept override {
+ std::cerr << "Error " << ec.message() << " while reading from socket"
+ << std::endl;
+ client_.io_service_.stop();
+ }
+
+ void readSuccess(std::size_t total_size) noexcept override {
+ Time t2 = std::chrono::steady_clock::now();
+ TimeDuration dt =
+ std::chrono::duration_cast<TimeDuration>(t2 - client_.t_download_);
+ long usec = (long)dt.count();
+
+ std::cout << "Content retrieved. Size: " << total_size << " [Bytes]"
+ << std::endl;
+
+ std::cerr << "Elapsed Time: " << usec / 1000000.0 << " seconds -- "
+ << (total_size * 8) * 1.0 / usec * 1.0 << " [Mbps]"
+ << std::endl;
+
+ client_.io_service_.stop();
+ }
+
+ private:
+ Impl &client_;
+ };
+
+ hiperf::ClientConfiguration configuration_;
+ Time t_stats_;
+ Time t_download_;
+ uint32_t total_duration_milliseconds_;
+ uint64_t old_bytes_value_;
+ uint64_t old_interest_tx_value_;
+ uint64_t old_fec_interest_tx_value_;
+ uint64_t old_fec_data_rx_value_;
+ uint64_t old_lost_data_value_;
+ uint64_t old_bytes_recovered_value_;
+ uint64_t old_definitely_lost_data_value_;
+ uint32_t old_retx_value_;
+ uint32_t old_sent_int_value_;
+ uint32_t old_received_nacks_value_;
+ uint32_t old_fec_pkt_;
+
+ // IMPORTANT: to be used only for performance testing, when consumer and
+ // producer are synchronized. Used for rtc only at the moment
+ double avg_data_delay_;
+ uint32_t delay_sample_;
+
+ uint32_t received_bytes_;
+ uint32_t received_data_pkt_;
+
+ std::string data_delays_;
+
+ asio::io_service io_service_;
+ asio::signal_set signals_;
+ RTCCallback rtc_callback_;
+ Callback callback_;
+ std::unique_ptr<ConsumerSocket> consumer_socket_;
+ std::unique_ptr<ProducerSocket> producer_socket_;
+ asio::ip::udp::socket socket_;
+ asio::ip::udp::endpoint remote_;
+
+ ForwarderConfiguration config_;
+ uint16_t switch_threshold_; /* ms */
+ bool done_;
+ std::vector<ForwarderInterface::RouteInfoPtr> main_routes_;
+ std::vector<ForwarderInterface::RouteInfoPtr> backup_routes_;
+#ifdef FORWARDER_INTERFACE
+ ForwarderInterface forwarder_interface_;
+#endif
+};
+
+HIperfClient::HIperfClient(const ClientConfiguration &conf) {
+ impl_ = new Impl(conf);
+}
+
+HIperfClient::~HIperfClient() { delete impl_; }
+
+int HIperfClient::setup() { return impl_->setup(); }
+
+void HIperfClient::run() { impl_->run(); }
+
+} // namespace hiperf
diff --git a/libtransport/includes/hicn/transport/interfaces/rtc_socket_producer.h b/apps/hiperf/src/client.h
index 218240f83..f45b9af43 100644
--- a/libtransport/includes/hicn/transport/interfaces/rtc_socket_producer.h
+++ b/apps/hiperf/src/client.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -15,18 +15,20 @@
#pragma once
-#include <hicn/transport/interfaces/socket_producer.h>
+#include <common.h>
-namespace transport {
+namespace hiperf {
-namespace interface {
-
-class RTCProducerSocket : public ProducerSocket {
+class HIperfClient {
public:
- RTCProducerSocket();
- ~RTCProducerSocket() = default;
-};
+ HIperfClient(const ClientConfiguration &conf);
+ ~HIperfClient();
+ int setup();
+ void run();
-} // namespace interface
+ private:
+ class Impl;
+ Impl *impl_;
+};
-} // end namespace transport
+} // namespace hiperf \ No newline at end of file
diff --git a/apps/hiperf/src/common.h b/apps/hiperf/src/common.h
new file mode 100644
index 000000000..e6ba526f9
--- /dev/null
+++ b/apps/hiperf/src/common.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/auth/identity.h>
+#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/config.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/interest.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+#include <hicn/transport/interfaces/p2psecure_socket_consumer.h>
+#include <hicn/transport/interfaces/p2psecure_socket_producer.h>
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <hicn/transport/interfaces/socket_producer.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
+#include <hicn/transport/utils/literals.h>
+
+#ifndef _WIN32
+#include <hicn/transport/utils/daemonizator.h>
+#endif
+
+#include <asio.hpp>
+#include <cmath>
+#include <fstream>
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <unordered_set>
+
+#ifndef ERROR_SUCCESS
+#define ERROR_SUCCESS 0
+#endif
+#define ERROR_SETUP -5
+#define MIN_PROBE_SEQ 0xefffffff
+
+using namespace transport::interface;
+using namespace transport::auth;
+using namespace transport::core;
+
+static inline uint64_t _ntohll(const uint64_t *input) {
+ uint64_t return_val;
+ uint8_t *tmp = (uint8_t *)&return_val;
+
+ tmp[0] = *input >> 56;
+ tmp[1] = *input >> 48;
+ tmp[2] = *input >> 40;
+ tmp[3] = *input >> 32;
+ tmp[4] = *input >> 24;
+ tmp[5] = *input >> 16;
+ tmp[6] = *input >> 8;
+ tmp[7] = *input >> 0;
+
+ return return_val;
+}
+
+static inline uint64_t _htonll(const uint64_t *input) {
+ return (_ntohll(input));
+}
+
+namespace hiperf {
+
+/**
+ * Class for handling the production rate for the RTC producer.
+ */
+class Rate {
+ public:
+ Rate() : rate_kbps_(0) {}
+
+ Rate(const std::string &rate) {
+ std::size_t found = rate.find("kbps");
+ if (found != std::string::npos) {
+ rate_kbps_ = std::stof(rate.substr(0, found));
+ } else {
+ throw std::runtime_error("Format " + rate + " not correct");
+ }
+ }
+
+ Rate(const Rate &other) : rate_kbps_(other.rate_kbps_) {}
+
+ Rate &operator=(const std::string &rate) {
+ std::size_t found = rate.find("kbps");
+ if (found != std::string::npos) {
+ rate_kbps_ = std::stof(rate.substr(0, found));
+ } else {
+ throw std::runtime_error("Format " + rate + " not correct");
+ }
+
+ return *this;
+ }
+
+ std::chrono::microseconds getMicrosecondsForPacket(std::size_t packet_size) {
+ return std::chrono::microseconds(
+ (uint32_t)std::round(packet_size * 1000.0 * 8.0 / (double)rate_kbps_));
+ }
+
+ private:
+ float rate_kbps_;
+};
+
+struct packet_t {
+ uint64_t timestamp;
+ uint32_t size;
+};
+
+/**
+ * Container for command line configuration for hiperf client.
+ */
+struct ClientConfiguration {
+ ClientConfiguration()
+ : name("b001::abcd", 0),
+ beta(-1.f),
+ drop_factor(-1.f),
+ window(-1),
+ producer_certificate(""),
+ passphrase(""),
+ receive_buffer(nullptr),
+ receive_buffer_size_(128 * 1024),
+ download_size(0),
+ report_interval_milliseconds_(1000),
+ transport_protocol_(CBR),
+ rtc_(false),
+ test_mode_(false),
+ relay_(false),
+ secure_(false),
+ producer_prefix_(),
+ interest_lifetime_(500),
+ relay_name_("c001::abcd/64"),
+ output_stream_mode_(false),
+ port_(0) {}
+
+ Name name;
+ double beta;
+ double drop_factor;
+ double window;
+ std::string producer_certificate;
+ std::string passphrase;
+ std::shared_ptr<utils::MemBuf> receive_buffer;
+ std::size_t receive_buffer_size_;
+ std::size_t download_size;
+ std::uint32_t report_interval_milliseconds_;
+ TransportProtocolAlgorithms transport_protocol_;
+ bool rtc_;
+ bool test_mode_;
+ bool relay_;
+ bool secure_;
+ Prefix producer_prefix_;
+ uint32_t interest_lifetime_;
+ Prefix relay_name_;
+ bool output_stream_mode_;
+ uint16_t port_;
+};
+
+/**
+ * Container for command line configuration for hiperf server.
+ */
+struct ServerConfiguration {
+ ServerConfiguration()
+ : name("b001::abcd/64"),
+ virtual_producer(true),
+ manifest(false),
+ live_production(false),
+ content_lifetime(600000000_U32),
+ download_size(20 * 1024 * 1024),
+ hash_algorithm(CryptoHashType::SHA256),
+ keystore_name(""),
+ passphrase(""),
+ keystore_password("cisco"),
+ multiphase_produce_(false),
+ rtc_(false),
+ interactive_(false),
+ trace_based_(false),
+ trace_index_(0),
+ trace_file_(nullptr),
+ production_rate_(std::string("2048kbps")),
+ payload_size_(1400),
+ secure_(false),
+ input_stream_mode_(false),
+ port_(0) {}
+
+ Prefix name;
+ bool virtual_producer;
+ bool manifest;
+ bool live_production;
+ std::uint32_t content_lifetime;
+ std::uint32_t download_size;
+ CryptoHashType hash_algorithm;
+ std::string keystore_name;
+ std::string passphrase;
+ std::string keystore_password;
+ bool multiphase_produce_;
+ bool rtc_;
+ bool interactive_;
+ bool trace_based_;
+ std::uint32_t trace_index_;
+ char *trace_file_;
+ Rate production_rate_;
+ std::size_t payload_size_;
+ bool secure_;
+ bool input_stream_mode_;
+ uint16_t port_;
+ std::vector<struct packet_t> trace_;
+};
+
+} // namespace hiperf
diff --git a/apps/hiperf/src/forwarder_config.h b/apps/hiperf/src/forwarder_config.h
new file mode 100644
index 000000000..655ac3b66
--- /dev/null
+++ b/apps/hiperf/src/forwarder_config.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace hiperf {
+
+struct ListenerConfig {
+ std::string address;
+ std::uint16_t port;
+ std::string interface;
+ std::string name;
+};
+
+struct ConnectorConfig {
+ std::string local_address;
+ std::uint16_t local_port;
+ std::string remote_address;
+ std::uint16_t remote_port;
+ std::string interface;
+ std::string name;
+};
+
+struct RouteConfig {
+ std::string prefix;
+ uint16_t weight;
+ std::string main_connector;
+ std::string backup_connector;
+ std::string name;
+};
+
+class ForwarderConfiguration {
+ public:
+ ForwarderConfiguration() : n_threads_(1) {}
+
+ bool empty() {
+ return listeners_.empty() && connectors_.empty() && routes_.empty();
+ }
+
+ ForwarderConfiguration &setThreadNumber(std::size_t threads) {
+ n_threads_ = threads;
+ return *this;
+ }
+
+ std::size_t getThreadNumber() { return n_threads_; }
+
+ template <typename... Args>
+ ForwarderConfiguration &addListener(Args &&...args) {
+ listeners_.emplace_back(std::forward<Args>(args)...);
+ return *this;
+ }
+
+ template <typename... Args>
+ ForwarderConfiguration &addConnector(const std::string &name,
+ Args &&...args) {
+ connectors_.emplace(name, std::forward<Args>(args)...);
+ return *this;
+ }
+
+ template <typename... Args>
+ ForwarderConfiguration &addRoute(Args &&...args) {
+ routes_.emplace_back(std::forward<Args>(args)...);
+ return *this;
+ }
+
+ std::vector<ListenerConfig> &getListeners() { return listeners_; }
+
+ std::unordered_map<std::string, ConnectorConfig> &getConnectors() {
+ return connectors_;
+ }
+
+ std::vector<RouteConfig> &getRoutes() { return routes_; }
+
+ private:
+ std::vector<ListenerConfig> listeners_;
+ std::unordered_map<std::string, ConnectorConfig> connectors_;
+ std::vector<RouteConfig> routes_;
+ std::size_t n_threads_;
+};
+
+} \ No newline at end of file
diff --git a/apps/hiperf/src/forwarder_interface.cc b/apps/hiperf/src/forwarder_interface.cc
new file mode 100644
index 000000000..864208239
--- /dev/null
+++ b/apps/hiperf/src/forwarder_interface.cc
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <arpa/inet.h>
+#include <forwarder_interface.h>
+#include <hicn/transport/utils/log.h>
+
+#include <chrono>
+#include <iostream>
+#include <thread>
+#include <unordered_set>
+
+extern "C" {
+#include <hicn/error.h>
+#include <hicn/util/ip_address.h>
+}
+
+// XXX the main listener should be retrieve in this class at initialization, aka
+// when hICN becomes avialable
+//
+// XXX the main listener port will be retrieved in the forwarder
+// interface... everything else will be delayed until we have this
+// information
+
+namespace hiperf {
+
+ForwarderInterface::ForwarderInterface(asio::io_service &io_service,
+ ICallback *callback)
+ : external_ioservice_(io_service),
+ forwarder_interface_callback_(callback),
+ work_(std::make_unique<asio::io_service::work>(internal_ioservice_)),
+ sock_(nullptr),
+ thread_(std::make_unique<std::thread>([this]() {
+ std::cout << "Starting Forwarder Interface thread" << std::endl;
+ internal_ioservice_.run();
+ std::cout << "Stopping Forwarder Interface thread" << std::endl;
+ })),
+ // set_route_callback_(std::forward<Callback &&>(setRouteCallback)),
+ check_routes_timer_(nullptr),
+ pending_add_route_counter_(0),
+ hicn_listen_port_(9695),
+ /* We start in disabled state even when a forwarder is always available */
+ state_(State::Disabled),
+ timer_(io_service),
+ num_reattempts(0) {
+ std::cout << "Forwarder interface created... connecting to forwarder...\n";
+ internal_ioservice_.post([this]() { onHicnServiceAvailable(true); });
+}
+
+ForwarderInterface::~ForwarderInterface() {
+ if (thread_ && thread_->joinable()) {
+ internal_ioservice_.dispatch([this]() {
+ if (sock_) {
+ hc_sock_free(sock_);
+ sock_ = nullptr;
+ }
+
+ work_.reset();
+ });
+
+ thread_->join();
+ }
+
+ std::cout << "ForwarderInterface::~ForwarderInterface" << std::endl;
+}
+
+void ForwarderInterface::onHicnServiceAvailable(bool flag) {
+ if (flag) {
+ switch (state_) {
+ case State::Disabled:
+ case State::Requested:
+ state_ = State::Available;
+ case State::Available:
+ connectToForwarder();
+ /* Synchronous */
+ if (state_ != State::Connected) {
+ std::cout << "ConnectToForwarder failed" << std::endl;
+ goto REATTEMPT;
+ }
+ state_ = State::Ready;
+
+ std::cout << "Connected to forwarder... cancelling reconnection timer"
+ << std::endl;
+ timer_.cancel();
+ num_reattempts = 0;
+
+ // case State::Connected:
+ // checkListener();
+
+ // if (state_ != State::Ready) {
+ // std::cout << "Listener not found" << std::endl;
+ // goto REATTEMPT;
+ // }
+ // state_ = State::Ready;
+
+ // timer_.cancel();
+ // num_reattempts = 0;
+
+ std::cout << "Forwarder interface is ready... communicate to controller"
+ << std::endl;
+
+ forwarder_interface_callback_->onHicnServiceReady();
+
+ case State::Ready:
+ break;
+ }
+ } else {
+ if (sock_) {
+ hc_sock_free(sock_);
+ sock_ = nullptr;
+ }
+ state_ = State::Disabled; // XXX to be checked upon callback to prevent the
+ // state from going forward (used to manage
+ // concurrency)
+ }
+ return;
+
+REATTEMPT:
+ /* Schedule reattempt */
+ std::cout << "Failed to connect, scheduling reattempt" << std::endl;
+ num_reattempts++;
+
+ timer_.expires_from_now(
+ std::chrono::milliseconds(ForwarderInterface::REATTEMPT_DELAY_MS));
+ // timer_.async_wait(std::bind(&ForwarderInterface::onHicnServiceAvailable,
+ // this, flag, std::placeholders::_1));
+ timer_.async_wait([this, flag](std::error_code ec) {
+ if (ec) return;
+ onHicnServiceAvailable(flag);
+ });
+}
+
+int ForwarderInterface::connectToForwarder() {
+ sock_ = hc_sock_create();
+ if (!sock_) {
+ std::cout << "Could not create socket" << std::endl;
+ goto ERR_SOCK;
+ }
+
+ if (hc_sock_connect(sock_) < 0) {
+ std::cout << "Could not connect to forwarder" << std::endl;
+ goto ERR;
+ }
+
+ std::cout << "Forwarder interface connected" << std::endl;
+ state_ = State::Connected;
+ return 0;
+
+ERR:
+ hc_sock_free(sock_);
+ sock_ = nullptr;
+ERR_SOCK:
+ return -1;
+}
+
+int ForwarderInterface::checkListener() {
+ if (!sock_) return -1;
+
+ hc_data_t *data;
+ if (hc_listener_list(sock_, &data) < 0) return -1;
+
+ int ret = -1;
+ foreach_listener(l, data) {
+ std::string interface = std::string(l->interface_name);
+ if (interface.compare("lo") != 0) {
+ hicn_listen_port_ = l->local_port;
+ state_ = State::Ready;
+ ret = 0;
+ std::cout << "Got listener port" << std::endl;
+ break;
+ }
+ }
+
+ hc_data_free(data);
+ return ret;
+}
+
+void ForwarderInterface::close() {
+ std::cout << "ForwarderInterface::close" << std::endl;
+
+ state_ = State::Disabled;
+ /* Cancelling eventual reattempts */
+ timer_.cancel();
+
+ if (sock_) {
+ hc_sock_free(sock_);
+ sock_ = nullptr;
+ }
+
+ internal_ioservice_.post([this]() { work_.reset(); });
+
+ if (thread_->joinable()) {
+ thread_->join();
+ }
+}
+
+#if 0
+void ForwarderInterface::enableCheckRoutesTimer() {
+ if (check_routes_timer_ != nullptr) return;
+
+ check_routes_timer_ =
+ std::make_unique<asio::steady_timer>(internal_ioservice_);
+ checkRoutesLoop();
+}
+
+void ForwarderInterface::removeConnectedUserNow(ProtocolPtr protocol) {
+ internalRemoveConnectedUser(protocol);
+}
+
+void ForwarderInterface::scheduleRemoveConnectedUser(ProtocolPtr protocol) {
+ internal_ioservice_.post(
+ [this, protocol]() { internalRemoveConnectedUser(protocol); });
+}
+#endif
+
+void ForwarderInterface::createFaceAndRoute(const RouteInfoPtr &route_info) {
+ std::vector<RouteInfoPtr> routes;
+ routes.push_back(std::move(route_info));
+ createFaceAndRoutes(routes);
+}
+
+void ForwarderInterface::createFaceAndRoutes(
+ const std::vector<RouteInfoPtr> &routes_info) {
+ pending_add_route_counter_++;
+ auto timer = new asio::steady_timer(internal_ioservice_);
+ internal_ioservice_.post([this, routes_info, timer]() {
+ internalCreateFaceAndRoutes(routes_info, ForwarderInterface::MAX_REATTEMPT,
+ timer);
+ });
+}
+
+void ForwarderInterface::deleteFaceAndRoute(const RouteInfoPtr &route_info) {
+ std::vector<RouteInfoPtr> routes;
+ routes.push_back(std::move(route_info));
+ deleteFaceAndRoutes(routes);
+}
+
+void ForwarderInterface::deleteFaceAndRoutes(
+ const std::vector<RouteInfoPtr> &routes_info) {
+ internal_ioservice_.post([this, routes_info]() {
+ for (auto &route : routes_info) {
+ internalDeleteFaceAndRoute(route);
+ }
+ });
+}
+
+void ForwarderInterface::internalDeleteFaceAndRoute(
+ const RouteInfoPtr &route_info) {
+ if (!sock_) return;
+
+ hc_data_t *data;
+ if (hc_route_list(sock_, &data) < 0) return;
+
+ std::vector<hc_route_t *> routes_to_remove;
+ foreach_route(r, data) {
+ char remote_addr[INET6_ADDRSTRLEN];
+ int ret = ip_address_ntop(&r->remote_addr, remote_addr, r->len, r->family);
+ if (ret < 0) continue;
+
+ std::string route_addr(remote_addr);
+ if (route_addr.compare(route_info->route_addr) == 0 &&
+ r->len == route_info->route_len) {
+ // route found
+ routes_to_remove.push_back(r);
+ }
+ }
+
+ if (routes_to_remove.size() == 0) {
+ // nothing to do here
+ hc_data_free(data);
+ return;
+ }
+
+ std::unordered_set<uint32_t> connids_to_remove;
+ for (unsigned i = 0; i < routes_to_remove.size(); i++) {
+ connids_to_remove.insert(routes_to_remove[i]->face_id);
+ if (hc_route_delete(sock_, routes_to_remove[i]) < 0) {
+ std::cout << "Error removing route from forwarder." << std::endl;
+ }
+ }
+
+ // remove connection
+ if (hc_connection_list(sock_, &data) < 0) {
+ hc_data_free(data);
+ return;
+ }
+
+ // collects pointerst to the connections using the conn IDs
+ std::vector<hc_connection_t *> conns_to_remove;
+ foreach_connection(c, data) {
+ if (connids_to_remove.find(c->id) != connids_to_remove.end()) {
+ // conn found
+ conns_to_remove.push_back(c);
+ }
+ }
+
+ if (conns_to_remove.size() == 0) {
+ // nothing else to do here
+ hc_data_free(data);
+ return;
+ }
+
+ for (unsigned i = 0; i < conns_to_remove.size(); i++) {
+ if (hc_connection_delete(sock_, conns_to_remove[i]) < 0) {
+ std::cout << "Error removing connection from forwarder." << std::endl;
+ }
+ }
+
+ hc_data_free(data);
+}
+
+void ForwarderInterface::internalCreateFaceAndRoutes(
+ const std::vector<RouteInfoPtr> &route_info, uint8_t max_try,
+ asio::steady_timer *timer) {
+ uint32_t face_id;
+
+ std::vector<RouteInfoPtr> failed;
+ for (auto &route : route_info) {
+ int ret = tryToCreateFace(route.get(), &face_id);
+ if (ret >= 0) {
+ auto ret = tryToCreateRoute(route.get(), face_id);
+ if (ret < 0) {
+ failed.push_back(route);
+ std::cerr << "Error creating route and face" << std::endl;
+ continue;
+ }
+ }
+ }
+
+ if (failed.size() > 0) {
+ if (max_try == 0) {
+ /* All attempts failed */
+ goto RESULT;
+ }
+ max_try--;
+ timer->expires_from_now(std::chrono::milliseconds(500));
+ timer->async_wait([this, failed, max_try, timer](std::error_code ec) {
+ if (ec) return;
+ internalCreateFaceAndRoutes(failed, max_try, timer);
+ });
+ return;
+ }
+
+#if 0
+ // route_status_[protocol] = std::move(route_info);
+ for (size_t i = 0; i < route_info.size(); i++) {
+ route_status_.insert(
+ std::pair<ClientId, RouteInfoPtr>(protocol, std::move(route_info[i])));
+ }
+#endif
+
+RESULT:
+ std::cout << "Face / Route create ok, now calling back protocol" << std::endl;
+ pending_add_route_counter_--;
+ external_ioservice_.post([this, r = std::move(route_info)]() mutable {
+ forwarder_interface_callback_->onRouteConfigured(r);
+ });
+ delete timer;
+}
+
+int ForwarderInterface::tryToCreateFace(RouteInfo *route_info,
+ uint32_t *face_id) {
+ bool found = false;
+
+ // check connection with the forwarder
+ if (!sock_) {
+ std::cout << "[ForwarderInterface::tryToCreateFace] socket error"
+ << std::endl;
+ goto ERR_SOCK;
+ }
+
+ // get listeners list
+ hc_data_t *data;
+ if (hc_listener_list(sock_, &data) < 0) {
+ std::cout << "[ForwarderInterface::tryToCreateFace] cannot list listeners";
+ goto ERR_LIST;
+ }
+
+ char _local_address[128];
+ foreach_listener(l, data) {
+ std::cout << "Processing " << l->interface_name << std::endl;
+ std::string interface = std::string(l->interface_name);
+ int ret = ip_address_ntop(&l->local_addr, _local_address, 128, AF_INET);
+ if (ret < 0) {
+ std::cerr << "Error in ip_address_ntop" << std::endl;
+ goto ERR;
+ }
+
+ std::string local_address = std::string(_local_address);
+ uint16_t local_port = l->local_port;
+
+ if (interface.compare(route_info->interface) == 0 &&
+ local_address.compare(route_info->local_addr) == 0 &&
+ local_port == route_info->local_port) {
+ found = true;
+ break;
+ }
+ }
+
+ std::cout << route_info->remote_addr << std::endl;
+
+ ip_address_t local_address, remote_address;
+ ip_address_pton(route_info->local_addr.c_str(), &local_address);
+ ip_address_pton(route_info->remote_addr.c_str(), &remote_address);
+
+ if (!found) {
+ // Create listener
+ hc_listener_t listener;
+ memset(&listener, 0, sizeof(hc_listener_t));
+
+ std::string name = "l_" + route_info->name;
+ listener.local_addr = local_address;
+ listener.type = CONNECTION_TYPE_UDP;
+ listener.family = AF_INET;
+ listener.local_port = route_info->local_port;
+ strncpy(listener.name, name.c_str(), sizeof(listener.name));
+ strncpy(listener.interface_name, route_info->interface.c_str(),
+ sizeof(listener.interface_name));
+
+ std::cout << "------------> " << route_info->interface << std::endl;
+
+ int ret = hc_listener_create(sock_, &listener);
+
+ if (ret < 0) {
+ std::cerr << "Error creating listener." << std::endl;
+ return -1;
+ } else {
+ std::cout << "Listener " << listener.id << " created." << std::endl;
+ }
+ }
+
+ // Create face
+ hc_face_t face;
+ memset(&face, 0, sizeof(hc_face_t));
+
+ // crate face with the local interest
+ face.face.type = FACE_TYPE_UDP;
+ face.face.family = route_info->family;
+ face.face.local_addr = local_address;
+ face.face.remote_addr = remote_address;
+ face.face.local_port = route_info->local_port;
+ face.face.remote_port = route_info->remote_port;
+
+ if (netdevice_set_name(&face.face.netdevice, route_info->interface.c_str()) <
+ 0) {
+ std::cout << "[ForwarderInterface::tryToCreateFaceAndRoute] "
+ "netdevice_set_name "
+ "("
+ << face.face.netdevice.name << ", "
+ << route_info->interface << ") error" << std::endl;
+ goto ERR;
+ }
+
+ // create face
+ if (hc_face_create(sock_, &face) < 0) {
+ std::cout << "[ForwarderInterface::tryToCreateFace] error creating face";
+ goto ERR;
+ }
+
+ std::cout << "Face created successfully" << std::endl;
+
+ // assing face to the return value
+ *face_id = face.id;
+
+ hc_data_free(data);
+ return 0;
+
+ERR:
+ hc_data_free(data);
+ERR_LIST:
+ERR_SOCK:
+ return -1;
+}
+
+int ForwarderInterface::tryToCreateRoute(RouteInfo *route_info,
+ uint32_t face_id) {
+ std::cout << "Trying to create route" << std::endl;
+
+ // check connection with the forwarder
+ if (!sock_) {
+ std::cout << "[ForwarderInterface::tryToCreateRoute] socket error";
+ return -1;
+ }
+
+ ip_address_t route_ip;
+ hc_route_t route;
+
+ if (ip_address_pton(route_info->route_addr.c_str(), &route_ip) < 0) {
+ std::cout << "[ForwarderInterface::tryToCreateRoute] ip_address_pton error";
+ return -1;
+ }
+
+ route.face_id = face_id;
+ route.family = AF_INET6;
+ route.remote_addr = route_ip;
+ route.len = route_info->route_len;
+ route.cost = 1;
+
+ if (hc_route_create(sock_, &route) < 0) {
+ std::cout << "[ForwarderInterface::tryToCreateRoute] error creating route";
+ return -1;
+ }
+
+ std::cout << "[ForwarderInterface::tryToCreateRoute] OK" << std::endl;
+ return 0;
+}
+
+#if 0 // not used
+void ForwarderInterface::checkRoutesLoop() {
+ check_routes_timer_->expires_from_now(std::chrono::milliseconds(1000));
+ check_routes_timer_->async_wait([this](std::error_code ec) {
+ if (ec) return;
+ if (pending_add_route_counter_ == 0) checkRoutes();
+ });
+}
+
+void ForwarderInterface::checkRoutes() {
+ std::cout << "someone called the checkRoutes function" << std::endl;
+ if (!sock_) return;
+
+ hc_data_t *data;
+ if (hc_route_list(sock_, &data) < 0) {
+ return;
+ }
+
+ std::unordered_set<std::string> routes_set;
+ foreach_route(r, data) {
+ char remote_addr[INET6_ADDRSTRLEN];
+ int ret = ip_address_ntop(&r->remote_addr, remote_addr, r->len, r->family);
+ if (ret < 0) continue;
+ std::string route(std::string(remote_addr) + "/" + std::to_string(r->len));
+ routes_set.insert(route);
+ }
+
+ for (auto it = route_status_.begin(); it != route_status_.end(); it++) {
+ std::string route(it->second->route_addr + "/" +
+ std::to_string(it->second->route_len));
+ if (routes_set.find(route) == routes_set.end()) {
+ // the route is missing
+ createFaceAndRoute(it->second, it->first);
+ break;
+ }
+ }
+
+ hc_data_free(data);
+}
+#endif
+
+#if 0
+ using ListenerRetrievedCallback =
+ std::function<void(std::error_code, uint32_t)>;
+
+ ListenerRetrievedCallback listener_retrieved_callback_;
+
+#ifdef __ANDROID__
+ hicn_listen_port_(9695),
+#else
+ hicn_listen_port_(0),
+#endif
+ timer_(forward_engine_.getIoService()),
+
+ void initConfigurationProtocol(void)
+ {
+ // We need the configuration, which is different for every protocol...
+ // so we move this step down towards the protocol implementation itself.
+ if (!permanent_hicn) {
+ doInitConfigurationProtocol();
+ } else {
+ // XXX This should be moved somewhere else
+ getMainListener(
+ [this](std::error_code ec, uint32_t hicn_listen_port) {
+ if (!ec)
+ {
+ hicn_listen_port_ = hicn_listen_port;
+ doInitConfigurationProtocol();
+ }
+ });
+ }
+ }
+
+ template <typename Callback>
+ void getMainListener(Callback &&callback)
+ {
+ listener_retrieved_callback_ = std::forward<Callback &&>(callback);
+ tryToConnectToForwarder();
+ }
+ private:
+ void doGetMainListener(std::error_code ec)
+ {
+ if (!ec)
+ {
+ // ec == 0 --> timer expired
+ int ret = forwarder_interface_.getMainListenerPort();
+ if (ret <= 0)
+ {
+ // Since without the main listener of the forwarder the proxy cannot
+ // work, we can stop the program here until we get the listener port.
+ std::cout <<
+ "Could not retrieve main listener port from the forwarder. "
+ "Retrying.";
+
+ timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
+ timer_.async_wait(std::bind(&Protocol::doGetMainListener, this,
+ std::placeholders::_1));
+ }
+ else
+ {
+ timer_.cancel();
+ retx_count_ = 0;
+ hicn_listen_port_ = uint16_t(ret);
+ listener_retrieved_callback_(
+ make_error_code(configuration_error::success), hicn_listen_port_);
+ }
+ }
+ else
+ {
+ std::cout << "Timer for retrieving main hicn listener canceled." << std::endl;
+ }
+ }
+
+ void tryToConnectToForwarder()
+ {
+ doTryToConnectToForwarder(std::make_error_code(std::errc(0)));
+ }
+
+ void doTryToConnectToForwarder(std::error_code ec)
+ {
+ if (!ec)
+ {
+ // ec == 0 --> timer expired
+ int ret = forwarder_interface_.connect();
+ if (ret < 0)
+ {
+ // We were not able to connect to the local forwarder. Do not give up
+ // and retry.
+ std::cout << "Could not connect to local forwarder. Retrying." << std::endl;
+
+ timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
+ timer_.async_wait(std::bind(&Protocol::doTryToConnectToForwarder, this,
+ std::placeholders::_1));
+ }
+ else
+ {
+ timer_.cancel();
+ retx_count_ = 0;
+ doGetMainListener(std::make_error_code(std::errc(0)));
+ }
+ }
+ else
+ {
+ std::cout << "Timer for re-trying forwarder connection canceled." << std::endl;
+ }
+ }
+
+
+ template <typename ProtocolImplementation>
+ constexpr uint32_t Protocol<ProtocolImplementation>::RETRY_INTERVAL;
+
+#endif
+
+constexpr uint32_t ForwarderInterface::REATTEMPT_DELAY_MS;
+constexpr uint32_t ForwarderInterface::MAX_REATTEMPT;
+
+} // namespace hiperf \ No newline at end of file
diff --git a/apps/hiperf/src/forwarder_interface.h b/apps/hiperf/src/forwarder_interface.h
new file mode 100644
index 000000000..7591ea257
--- /dev/null
+++ b/apps/hiperf/src/forwarder_interface.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+extern "C" {
+#ifndef WITH_POLICY
+#define WITH_POLICY
+#endif
+#include <hicn/ctrl/api.h>
+#include <hicn/util/ip_address.h>
+}
+
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE
+#endif
+#include <asio.hpp>
+
+#include <functional>
+#include <thread>
+#include <unordered_map>
+
+namespace hiperf {
+
+class ForwarderInterface {
+ static const uint32_t REATTEMPT_DELAY_MS = 500;
+ static const uint32_t MAX_REATTEMPT = 10;
+
+ public:
+ struct RouteInfo {
+ int family;
+ std::string local_addr;
+ uint16_t local_port;
+ std::string remote_addr;
+ uint16_t remote_port;
+ std::string route_addr;
+ uint8_t route_len;
+ std::string interface;
+ std::string name;
+ };
+
+ using RouteInfoPtr = std::shared_ptr<RouteInfo>;
+
+ class ICallback {
+ public:
+ virtual void onHicnServiceReady() = 0;
+ virtual void onRouteConfigured(std::vector<RouteInfoPtr> &route_info) = 0;
+ };
+
+ enum class State {
+ Disabled, /* Stack is stopped */
+ Requested, /* Stack is starting */
+ Available, /* Forwarder is running */
+ Connected, /* Control socket connected */
+ Ready, /* Listener present */
+ };
+
+ public:
+ ForwarderInterface(asio::io_service &io_service, ICallback *callback);
+
+ ~ForwarderInterface();
+
+ State getState();
+
+ void setState(State state);
+
+ void onHicnServiceAvailable(bool flag);
+
+ void enableCheckRoutesTimer();
+
+ void createFaceAndRoutes(const std::vector<RouteInfoPtr> &routes_info);
+
+ void createFaceAndRoute(const RouteInfoPtr &route_info);
+
+ void deleteFaceAndRoutes(const std::vector<RouteInfoPtr> &routes_info);
+
+ void deleteFaceAndRoute(const RouteInfoPtr &route_info);
+
+ void close();
+
+ uint16_t getHicnListenerPort() { return hicn_listen_port_; }
+
+ private:
+ int connectToForwarder();
+
+ int checkListener();
+
+ void internalCreateFaceAndRoutes(const std::vector<RouteInfoPtr> &route_info,
+ uint8_t max_try, asio::steady_timer *timer);
+
+ void internalDeleteFaceAndRoute(const RouteInfoPtr &routes_info);
+
+ int tryToCreateFace(RouteInfo *RouteInfo, uint32_t *face_id);
+ int tryToCreateRoute(RouteInfo *RouteInfo, uint32_t face_id);
+
+ void checkRoutesLoop();
+
+ void checkRoutes();
+
+ asio::io_service &external_ioservice_;
+ asio::io_service internal_ioservice_;
+ ICallback *forwarder_interface_callback_;
+ std::unique_ptr<asio::io_service::work> work_;
+ hc_sock_t *sock_;
+ std::unique_ptr<std::thread> thread_;
+ // SetRouteCallback set_route_callback_;
+ // std::unordered_multimap<ProtocolPtr, RouteInfoPtr> route_status_;
+ std::unique_ptr<asio::steady_timer> check_routes_timer_;
+ uint32_t pending_add_route_counter_;
+ uint16_t hicn_listen_port_;
+
+ State state_;
+
+ /* Reattempt timer */
+ asio::steady_timer timer_;
+ unsigned num_reattempts;
+};
+
+} // namespace hiperf
diff --git a/apps/hiperf/src/main.cc b/apps/hiperf/src/main.cc
new file mode 100644
index 000000000..b2d99c4a4
--- /dev/null
+++ b/apps/hiperf/src/main.cc
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <client.h>
+#include <server.h>
+#include <forwarder_interface.h>
+
+namespace hiperf {
+
+void usage() {
+ std::cerr << "HIPERF - A tool for performing network throughput "
+ "measurements with hICN"
+ << std::endl;
+ std::cerr << "usage: hiperf [-S|-C] [options] [prefix|name]" << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "SERVER OR CLIENT:" << std::endl;
+#ifndef _WIN32
+ std::cerr << "-D\t\t\t\t\t"
+ << "Run as a daemon" << std::endl;
+ std::cerr << "-R\t\t\t\t\t"
+ << "Run RTC protocol (client or server)" << std::endl;
+ std::cerr << "-f\t<filename>\t\t\t"
+ << "Log file" << std::endl;
+ std::cerr << "-z\t<io_module>\t\t\t"
+ << "IO module to use. Default: hicnlight_module" << std::endl;
+#endif
+ std::cerr << std::endl;
+ std::cerr << "SERVER SPECIFIC:" << std::endl;
+ std::cerr << "-A\t<content_size>\t\t\t"
+ "Size of the content to publish. This "
+ "is not the size of the packet (see -s for it)."
+ << std::endl;
+ std::cerr << "-s\t<packet_size>\t\t\tSize of the payload of each data packet."
+ << std::endl;
+ std::cerr << "-r\t\t\t\t\t"
+ << "Produce real content of <content_size> bytes" << std::endl;
+ std::cerr << "-m\t\t\t\t\t"
+ << "Produce transport manifest" << std::endl;
+ std::cerr << "-l\t\t\t\t\t"
+ << "Start producing content upon the reception of the "
+ "first interest"
+ << std::endl;
+ std::cerr << "-K\t<keystore_path>\t\t\t"
+ << "Path of p12 file containing the "
+ "crypto material used for signing packets"
+ << std::endl;
+ std::cerr << "-k\t<passphrase>\t\t\t"
+ << "String from which a 128-bit symmetric key will be "
+ "derived for signing packets"
+ << std::endl;
+ std::cerr << "-y\t<hash_algorithm>\t\t"
+ << "Use the selected hash algorithm for "
+ "calculating manifest digests"
+ << std::endl;
+ std::cerr << "-p\t<password>\t\t\t"
+ << "Password for p12 keystore" << std::endl;
+ std::cerr << "-x\t\t\t\t\t"
+ << "Produce a content of <content_size>, then after downloading "
+ "it produce a new content of"
+ << "\n\t\t\t\t\t<content_size> without resetting "
+ "the suffix to 0."
+ << std::endl;
+ std::cerr << "-B\t<bitrate>\t\t\t"
+ << "Bitrate for RTC producer, to be used with the -R option."
+ << std::endl;
+#ifndef _WIN32
+ std::cerr << "-I\t\t\t\t\t"
+ "Interactive mode, start/stop real time content production "
+ "by pressing return. To be used with the -R option"
+ << std::endl;
+ std::cerr
+ << "-T\t<filename>\t\t\t"
+ "Trace based mode, hiperf takes as input a file with a trace. "
+ "Each line of the file indicates the timestamp and the size of "
+ "the packet to generate. To be used with the -R option. -B and -I "
+ "will be ignored."
+ << std::endl;
+ std::cerr << "-E\t\t\t\t\t"
+ << "Enable encrypted communication. Requires the path to a p12 "
+ "file containing the "
+ "crypto material used for the TLS handshake"
+ << std::endl;
+ std::cerr << "-G\t<port>\t\t\t"
+ << "input stream from localhost at the specified port" << std::endl;
+#endif
+ std::cerr << std::endl;
+ std::cerr << "CLIENT SPECIFIC:" << std::endl;
+ std::cerr << "-b\t<beta_parameter>\t\t"
+ << "RAAQM beta parameter" << std::endl;
+ std::cerr << "-d\t<drop_factor_parameter>\t\t"
+ << "RAAQM drop factor "
+ "parameter"
+ << std::endl;
+ std::cerr << "-L\t<interest lifetime>\t\t"
+ << "Set interest lifetime." << std::endl;
+ std::cerr << "-M\t<input_buffer_size>\t\t"
+ << "Size of consumer input buffer. If 0, reassembly of packets "
+ "will be disabled."
+ << std::endl;
+ std::cerr << "-W\t<window_size>\t\t\t"
+ << "Use a fixed congestion window "
+ "for retrieving the data."
+ << std::endl;
+ std::cerr << "-i\t<stats_interval>\t\t"
+ << "Show the statistics every <stats_interval> milliseconds."
+ << std::endl;
+ std::cerr << "-c\t<certificate_path>\t\t"
+ << "Path of the producer certificate to be used for verifying the "
+ "origin of the packets received."
+ << std::endl;
+ std::cerr << "-k\t<passphrase>\t\t\t"
+ << "String from which is derived the symmetric key used by the "
+ "producer to sign packets and by the consumer to verify them."
+ << std::endl;
+ std::cerr << "-t\t\t\t\t\t"
+ "Test mode, check if the client is receiving the "
+ "correct data. This is an RTC specific option, to be "
+ "used with the -R (default false)"
+ << std::endl;
+ std::cerr << "-P\t\t\t\t\t"
+ << "Prefix of the producer where to do the handshake" << std::endl;
+ std::cerr << "-j\t<relay_name>\t\t\t"
+ << "Publish the received content under the name relay_name."
+ "This is an RTC specific option, to be "
+ "used with the -R (default false)"
+ << std::endl;
+ std::cerr << "-g\t<port>\t\t\t"
+ << "output stream to localhost at the specified port" << std::endl;
+}
+
+int main(int argc, char *argv[]) {
+#ifndef _WIN32
+ // Common
+ bool daemon = false;
+#else
+ WSADATA wsaData = {0};
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+#endif
+
+ // -1 server, 0 undefined, 1 client
+ int role = 0;
+ int options = 0;
+
+ char *log_file = nullptr;
+ transport::interface::global_config::IoModuleConfiguration config;
+ std::string conf_file;
+ config.name = "hicnlight_module";
+
+ // Consumer
+ ClientConfiguration client_configuration;
+
+ // Producer
+ ServerConfiguration server_configuration;
+
+ int opt;
+#ifndef _WIN32
+ while ((opt = getopt(
+ argc, argv,
+ "DSCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xE:P:B:ItL:z:T:F:j:g:G:")) !=
+ -1) {
+ switch (opt) {
+ // Common
+ case 'D': {
+ daemon = true;
+ break;
+ }
+ case 'I': {
+ server_configuration.interactive_ = true;
+ server_configuration.trace_based_ = false;
+ server_configuration.input_stream_mode_ = false;
+ break;
+ }
+ case 'T': {
+ server_configuration.interactive_ = false;
+ server_configuration.trace_based_ = true;
+ server_configuration.input_stream_mode_ = false;
+ server_configuration.trace_file_ = optarg;
+ break;
+ }
+ case 'G': {
+ server_configuration.interactive_ = false;
+ server_configuration.trace_based_ = false;
+ server_configuration.input_stream_mode_ = true;
+ server_configuration.port_ = std::stoul(optarg);
+ break;
+ }
+ case 'g': {
+ client_configuration.output_stream_mode_ = true;
+ client_configuration.port_ = std::stoul(optarg);
+ break;
+ }
+#else
+ while ((opt = getopt(argc, argv,
+ "SCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xB:E:P:tL:z:F:j:")) !=
+ -1) {
+ switch (opt) {
+#endif
+ case 'f': {
+ log_file = optarg;
+ break;
+ }
+ case 'R': {
+ client_configuration.rtc_ = true;
+ server_configuration.rtc_ = true;
+ break;
+ }
+ case 'z': {
+ config.name = optarg;
+ break;
+ }
+ case 'F': {
+ conf_file = optarg;
+ break;
+ }
+
+ // Server or Client
+ case 'S': {
+ role -= 1;
+ break;
+ }
+ case 'C': {
+ role += 1;
+ break;
+ }
+ case 'k': {
+ server_configuration.passphrase = std::string(optarg);
+ client_configuration.passphrase = std::string(optarg);
+ break;
+ }
+
+ // Client specifc
+ case 'b': {
+ client_configuration.beta = std::stod(optarg);
+ options = 1;
+ break;
+ }
+ case 'd': {
+ client_configuration.drop_factor = std::stod(optarg);
+ options = 1;
+ break;
+ }
+ case 'W': {
+ client_configuration.window = std::stod(optarg);
+ options = 1;
+ break;
+ }
+ case 'M': {
+ client_configuration.receive_buffer_size_ = std::stoull(optarg);
+ options = 1;
+ break;
+ }
+ case 'P': {
+ client_configuration.producer_prefix_ = Prefix(optarg);
+ client_configuration.secure_ = true;
+ break;
+ }
+ case 'c': {
+ client_configuration.producer_certificate = std::string(optarg);
+ options = 1;
+ break;
+ }
+ case 'i': {
+ client_configuration.report_interval_milliseconds_ = std::stoul(optarg);
+ options = 1;
+ break;
+ }
+ case 't': {
+ client_configuration.test_mode_ = true;
+ options = 1;
+ break;
+ }
+ case 'L': {
+ client_configuration.interest_lifetime_ = std::stoul(optarg);
+ options = 1;
+ break;
+ }
+ case 'j': {
+ client_configuration.relay_ = true;
+ client_configuration.relay_name_ = Prefix(optarg);
+ options = 1;
+ break;
+ }
+ // Server specific
+ case 'A': {
+ server_configuration.download_size = std::stoul(optarg);
+ options = -1;
+ break;
+ }
+ case 's': {
+ server_configuration.payload_size_ = std::stoul(optarg);
+ options = -1;
+ break;
+ }
+ case 'r': {
+ server_configuration.virtual_producer = false;
+ options = -1;
+ break;
+ }
+ case 'm': {
+ server_configuration.manifest = true;
+ options = -1;
+ break;
+ }
+ case 'l': {
+ server_configuration.live_production = true;
+ options = -1;
+ break;
+ }
+ case 'K': {
+ server_configuration.keystore_name = std::string(optarg);
+ options = -1;
+ break;
+ }
+ case 'y': {
+ if (strncasecmp(optarg, "sha256", 6) == 0) {
+ server_configuration.hash_algorithm = CryptoHashType::SHA256;
+ } else if (strncasecmp(optarg, "sha512", 6) == 0) {
+ server_configuration.hash_algorithm = CryptoHashType::SHA512;
+ } else if (strncasecmp(optarg, "blake2b512", 10) == 0) {
+ server_configuration.hash_algorithm = CryptoHashType::BLAKE2B512;
+ } else if (strncasecmp(optarg, "blake2s256", 10) == 0) {
+ server_configuration.hash_algorithm = CryptoHashType::BLAKE2S256;
+ } else {
+ std::cerr << "Ignored unknown hash algorithm. Using SHA 256."
+ << std::endl;
+ }
+ options = -1;
+ break;
+ }
+ case 'p': {
+ server_configuration.keystore_password = std::string(optarg);
+ options = -1;
+ break;
+ }
+ case 'x': {
+ server_configuration.multiphase_produce_ = true;
+ options = -1;
+ break;
+ }
+ case 'B': {
+ auto str = std::string(optarg);
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+ server_configuration.production_rate_ = str;
+ options = -1;
+ break;
+ }
+ case 'E': {
+ server_configuration.keystore_name = std::string(optarg);
+ server_configuration.secure_ = true;
+ break;
+ }
+ case 'h':
+ default:
+ usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (options > 0 && role < 0) {
+ std::cerr << "Client options cannot be used when using the "
+ "software in server mode"
+ << std::endl;
+ usage();
+ return EXIT_FAILURE;
+ } else if (options < 0 && role > 0) {
+ std::cerr << "Server options cannot be used when using the "
+ "software in client mode"
+ << std::endl;
+ usage();
+ return EXIT_FAILURE;
+ } else if (!role) {
+ std::cerr << "Please specify if running hiperf as client "
+ "or server."
+ << std::endl;
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ if (argv[optind] == 0) {
+ std::cerr << "Please specify the name/prefix to use." << std::endl;
+ usage();
+ return EXIT_FAILURE;
+ } else {
+ if (role > 0) {
+ client_configuration.name = Name(argv[optind]);
+ } else {
+ server_configuration.name = Prefix(argv[optind]);
+ }
+ }
+
+ if (log_file) {
+#ifndef _WIN32
+ int fd = open(log_file, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR);
+ dup2(fd, STDOUT_FILENO);
+ dup2(STDOUT_FILENO, STDERR_FILENO);
+ close(fd);
+#else
+ int fd =
+ _open(log_file, _O_WRONLY | _O_APPEND | _O_CREAT, _S_IWRITE | _S_IREAD);
+ _dup2(fd, _fileno(stdout));
+ _dup2(_fileno(stdout), _fileno(stderr));
+ _close(fd);
+#endif
+ }
+
+#ifndef _WIN32
+ if (daemon) {
+ utils::Daemonizator::daemonize(false);
+ }
+#endif
+
+ /**
+ * IO module configuration
+ */
+ config.set();
+
+ // Parse config file
+ transport::interface::global_config::parseConfigurationFile(conf_file);
+
+ if (role > 0) {
+ HIperfClient c(client_configuration);
+ if (c.setup() != ERROR_SETUP) {
+ c.run();
+ }
+ } else if (role < 0) {
+ HIperfServer s(server_configuration);
+ if (s.setup() != ERROR_SETUP) {
+ s.run();
+ }
+ } else {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+#ifdef _WIN32
+ WSACleanup();
+#endif
+
+ return 0;
+}
+
+} // namespace hiperf
+
+int main(int argc, char *argv[]) { return hiperf::main(argc, argv); }
diff --git a/apps/hiperf/src/server.cc b/apps/hiperf/src/server.cc
new file mode 100644
index 000000000..968d42e2c
--- /dev/null
+++ b/apps/hiperf/src/server.cc
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <server.h>
+
+namespace hiperf {
+
+/**
+ * Hiperf server class: configure and setup an hicn producer following the
+ * ServerConfiguration.
+ */
+class HIperfServer::Impl {
+ const std::size_t log2_content_object_buffer_size = 8;
+
+ public:
+ Impl(const hiperf::ServerConfiguration &conf)
+ : configuration_(conf),
+ signals_(io_service_),
+ rtc_timer_(io_service_),
+ unsatisfied_interests_(),
+ content_objects_((std::uint16_t)(1 << log2_content_object_buffer_size)),
+ content_objects_index_(0),
+ mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1),
+ last_segment_(0),
+#ifndef _WIN32
+ ptr_last_segment_(&last_segment_),
+ input_(io_service_),
+ rtc_running_(false),
+#else
+ ptr_last_segment_(&last_segment_),
+#endif
+ flow_name_(configuration_.name.getName()),
+ socket_(io_service_),
+ recv_buffer_(nullptr, 0) {
+ std::string buffer(configuration_.payload_size_, 'X');
+ std::cout << "Producing contents under name " << conf.name.getName()
+ << std::endl;
+#ifndef _WIN32
+ if (configuration_.interactive_) {
+ input_.assign(::dup(STDIN_FILENO));
+ }
+#endif
+
+ for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) {
+ content_objects_[i] = ContentObject::Ptr(
+ new ContentObject(conf.name.getName(), HF_INET6_TCP, 0,
+ (const uint8_t *)buffer.data(), buffer.size()));
+ content_objects_[i]->setLifetime(
+ default_values::content_object_expiry_time);
+ }
+ }
+
+ void virtualProcessInterest(ProducerSocket &p, const Interest &interest) {
+ content_objects_[content_objects_index_ & mask_]->setName(
+ interest.getName());
+ producer_socket_->produce(
+ *content_objects_[content_objects_index_++ & mask_]);
+ }
+
+ void processInterest(ProducerSocket &p, const Interest &interest) {
+ p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)VOID_HANDLER);
+ p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
+ 5000000_U32);
+
+ produceContent(p, interest.getName(), interest.getName().getSuffix());
+ std::cout << "Received interest " << interest.getName().getSuffix()
+ << std::endl;
+ }
+
+ void asyncProcessInterest(ProducerSocket &p, const Interest &interest) {
+ p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)bind(&Impl::cacheMiss, this,
+ std::placeholders::_1,
+ std::placeholders::_2));
+ p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
+ 5000000_U32);
+ uint32_t suffix = interest.getName().getSuffix();
+
+ if (suffix == 0) {
+ last_segment_ = 0;
+ ptr_last_segment_ = &last_segment_;
+ unsatisfied_interests_.clear();
+ }
+
+ // The suffix will either be the one from the received interest or the
+ // smallest suffix of a previous interest not satisfed
+ if (!unsatisfied_interests_.empty()) {
+ auto it =
+ std::lower_bound(unsatisfied_interests_.begin(),
+ unsatisfied_interests_.end(), *ptr_last_segment_);
+ if (it != unsatisfied_interests_.end()) {
+ suffix = *it;
+ }
+ unsatisfied_interests_.erase(unsatisfied_interests_.begin(), it);
+ }
+
+ std::cout << "Received interest " << interest.getName().getSuffix()
+ << ", starting production at " << suffix << std::endl;
+ std::cout << unsatisfied_interests_.size() << " interests still unsatisfied"
+ << std::endl;
+ produceContentAsync(p, interest.getName(), suffix);
+ }
+
+ void produceContent(ProducerSocket &p, const Name &content_name,
+ uint32_t suffix) {
+ auto b = utils::MemBuf::create(configuration_.download_size);
+ std::memset(b->writableData(), '?', configuration_.download_size);
+ b->append(configuration_.download_size);
+ uint32_t total;
+
+ utils::TimePoint t0 = utils::SteadyClock::now();
+ total = p.produceStream(content_name, std::move(b),
+ !configuration_.multiphase_produce_, suffix);
+ utils::TimePoint t1 = utils::SteadyClock::now();
+
+ std::cout
+ << "Written " << total
+ << " data packets in output buffer (Segmentation time: "
+ << std::chrono::duration_cast<utils::Microseconds>(t1 - t0).count()
+ << " us)" << std::endl;
+ }
+
+ void produceContentAsync(ProducerSocket &p, Name content_name,
+ uint32_t suffix) {
+ auto b = utils::MemBuf::create(configuration_.download_size);
+ std::memset(b->writableData(), '?', configuration_.download_size);
+ b->append(configuration_.download_size);
+
+ p.asyncProduce(content_name, std::move(b),
+ !configuration_.multiphase_produce_, suffix,
+ &ptr_last_segment_);
+ }
+
+ void cacheMiss(ProducerSocket &p, const Interest &interest) {
+ unsatisfied_interests_.push_back(interest.getName().getSuffix());
+ }
+
+ void onContentProduced(ProducerSocket &p, const std::error_code &err,
+ uint64_t bytes_written) {
+ p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)bind(
+ &Impl::asyncProcessInterest, this,
+ std::placeholders::_1, std::placeholders::_2));
+ }
+
+ std::shared_ptr<Identity> getProducerIdentity(std::string &keystore_path,
+ std::string &keystore_pwd,
+ CryptoHashType &hash_type) {
+ if (access(keystore_path.c_str(), F_OK) != -1) {
+ return std::make_shared<Identity>(keystore_path, keystore_pwd, hash_type);
+ }
+ return std::make_shared<Identity>(keystore_path, keystore_pwd,
+ CryptoSuite::RSA_SHA256, 1024, 365,
+ "producer-test");
+ }
+
+ int setup() {
+ int ret;
+ int production_protocol;
+
+ if (configuration_.secure_) {
+ auto identity = getProducerIdentity(configuration_.keystore_name,
+ configuration_.keystore_password,
+ configuration_.hash_algorithm);
+ producer_socket_ = std::make_unique<P2PSecureProducerSocket>(
+ configuration_.rtc_, identity);
+ } else {
+ if (!configuration_.rtc_) {
+ production_protocol = ProductionProtocolAlgorithms::BYTE_STREAM;
+ } else {
+ production_protocol = ProductionProtocolAlgorithms::RTC_PROD;
+ }
+
+ producer_socket_ = std::make_unique<ProducerSocket>(production_protocol);
+ }
+
+ if (producer_socket_->setSocketOption(
+ GeneralTransportOptions::MAKE_MANIFEST, configuration_.manifest) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (!configuration_.passphrase.empty()) {
+ std::shared_ptr<Signer> signer = std::make_shared<SymmetricSigner>(
+ CryptoSuite::HMAC_SHA256, configuration_.passphrase);
+ producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER,
+ signer);
+ }
+
+ if (!configuration_.keystore_name.empty()) {
+ auto identity = getProducerIdentity(configuration_.keystore_name,
+ configuration_.keystore_password,
+ configuration_.hash_algorithm);
+ std::shared_ptr<Signer> signer = identity->getSigner();
+ producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER,
+ signer);
+ }
+
+ uint32_t rtc_header_size = 0;
+ if (configuration_.rtc_) rtc_header_size = 12;
+ producer_socket_->setSocketOption(
+ GeneralTransportOptions::DATA_PACKET_SIZE,
+ (uint32_t)(
+ configuration_.payload_size_ + rtc_header_size +
+ (configuration_.name.getAddressFamily() == AF_INET ? 40 : 60)));
+ producer_socket_->registerPrefix(configuration_.name);
+ producer_socket_->connect();
+
+ if (configuration_.rtc_) {
+ std::cout << "Running RTC producer: the prefix length will be ignored."
+ " Use /128 by default in RTC mode"
+ << std::endl;
+ return ERROR_SUCCESS;
+ }
+
+ if (!configuration_.virtual_producer) {
+ if (producer_socket_->setSocketOption(
+ GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
+ configuration_.content_lifetime) == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (producer_socket_->setSocketOption(
+ GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 200000U) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (!configuration_.live_production) {
+ produceContent(*producer_socket_, configuration_.name.getName(), 0);
+ } else {
+ ret = producer_socket_->setSocketOption(
+ ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)bind(&Impl::asyncProcessInterest, this,
+ std::placeholders::_1,
+ std::placeholders::_2));
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+ } else {
+ ret = producer_socket_->setSocketOption(
+ GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U);
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ ret = producer_socket_->setSocketOption(
+ ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)bind(&Impl::virtualProcessInterest, this,
+ std::placeholders::_1,
+ std::placeholders::_2));
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
+
+ ret = producer_socket_->setSocketOption(
+ ProducerCallbacksOptions::CONTENT_PRODUCED,
+ (ProducerContentCallback)bind(
+ &Impl::onContentProduced, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3));
+
+ return ERROR_SUCCESS;
+ }
+
+ void receiveStream() {
+ socket_.async_receive_from(
+ asio::buffer(recv_buffer_.first, recv_buffer_.second), remote_,
+ [this](std::error_code ec, std::size_t length) {
+ if (ec) return;
+ sendRTCContentFromStream(recv_buffer_.first, length);
+ receiveStream();
+ });
+ }
+
+ void sendRTCContentFromStream(uint8_t *buff, std::size_t len) {
+ auto payload =
+ content_objects_[content_objects_index_++ & mask_]->getPayload();
+ // this is used to compute the data packet delay
+ // Used only for performance evaluation
+ // It requires clock synchronization between producer and consumer
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+ uint8_t *start = (uint8_t *)payload->writableData();
+ std::memcpy(start, &now, sizeof(uint64_t));
+ std::memcpy(start + sizeof(uint64_t), buff, len);
+ producer_socket_->produceDatagram(flow_name_, start,
+ len + sizeof(uint64_t));
+ }
+
+ void sendRTCContentObjectCallback(std::error_code ec) {
+ if (ec) return;
+ rtc_timer_.expires_from_now(
+ configuration_.production_rate_.getMicrosecondsForPacket(
+ configuration_.payload_size_));
+ rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback, this,
+ std::placeholders::_1));
+ auto payload =
+ content_objects_[content_objects_index_++ & mask_]->getPayload();
+
+ // this is used to compute the data packet delay
+ // Used only for performance evaluation
+ // It requires clock synchronization between producer and consumer
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+
+ std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
+
+ producer_socket_->produceDatagram(
+ flow_name_, payload->data(),
+ payload->length() < 1400 ? payload->length() : 1400);
+ }
+
+ void sendRTCContentObjectCallbackWithTrace(std::error_code ec) {
+ if (ec) return;
+
+ auto payload =
+ content_objects_[content_objects_index_++ & mask_]->getPayload();
+
+ uint32_t packet_len =
+ configuration_.trace_[configuration_.trace_index_].size;
+
+ // this is used to compute the data packet delay
+ // used only for performance evaluation
+ // it requires clock synchronization between producer and consumer
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+
+ std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
+
+ if (packet_len > payload->length()) packet_len = payload->length();
+ if (packet_len > 1400) packet_len = 1400;
+
+ producer_socket_->produceDatagram(flow_name_, payload->data(), packet_len);
+
+ uint32_t next_index = configuration_.trace_index_ + 1;
+ uint64_t schedule_next;
+ if (next_index < configuration_.trace_.size()) {
+ schedule_next =
+ configuration_.trace_[next_index].timestamp -
+ configuration_.trace_[configuration_.trace_index_].timestamp;
+ } else {
+ // here we need to loop, schedule in a random time
+ schedule_next = 1000;
+ }
+
+ configuration_.trace_index_ =
+ (configuration_.trace_index_ + 1) % configuration_.trace_.size();
+ rtc_timer_.expires_from_now(std::chrono::microseconds(schedule_next));
+ rtc_timer_.async_wait(
+ std::bind(&Impl::sendRTCContentObjectCallbackWithTrace, this,
+ std::placeholders::_1));
+ }
+
+#ifndef _WIN32
+ void handleInput(const std::error_code &error, std::size_t length) {
+ if (error) {
+ producer_socket_->stop();
+ io_service_.stop();
+ }
+
+ if (rtc_running_) {
+ std::cout << "stop real time content production" << std::endl;
+ rtc_running_ = false;
+ rtc_timer_.cancel();
+ } else {
+ std::cout << "start real time content production" << std::endl;
+ rtc_running_ = true;
+ rtc_timer_.expires_from_now(
+ configuration_.production_rate_.getMicrosecondsForPacket(
+ configuration_.payload_size_));
+ rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback, this,
+ std::placeholders::_1));
+ }
+
+ input_buffer_.consume(length); // Remove newline from input.
+ asio::async_read_until(
+ input_, input_buffer_, '\n',
+ std::bind(&Impl::handleInput, this, std::placeholders::_1,
+ std::placeholders::_2));
+ }
+#endif
+
+ int parseTraceFile() {
+ std::ifstream trace(configuration_.trace_file_);
+ if (trace.fail()) {
+ return -1;
+ }
+ std::string line;
+ while (std::getline(trace, line)) {
+ std::istringstream iss(line);
+ hiperf::packet_t packet;
+ iss >> packet.timestamp >> packet.size;
+ configuration_.trace_.push_back(packet);
+ }
+ return 0;
+ }
+
+ int run() {
+ std::cerr << "Starting to serve consumers" << std::endl;
+
+ signals_.add(SIGINT);
+ signals_.async_wait([this](const std::error_code &, const int &) {
+ std::cout << "STOPPING!!" << std::endl;
+ producer_socket_->stop();
+ io_service_.stop();
+ });
+
+ if (configuration_.rtc_) {
+#ifndef _WIN32
+ if (configuration_.interactive_) {
+ asio::async_read_until(
+ input_, input_buffer_, '\n',
+ std::bind(&Impl::handleInput, this, std::placeholders::_1,
+ std::placeholders::_2));
+ } else if (configuration_.trace_based_) {
+ std::cout << "trace-based mode enabled" << std::endl;
+ if (configuration_.trace_file_ == nullptr) {
+ std::cout << "cannot find the trace file" << std::endl;
+ return ERROR_SETUP;
+ }
+ if (parseTraceFile() < 0) {
+ std::cout << "cannot parse the trace file" << std::endl;
+ return ERROR_SETUP;
+ }
+ rtc_running_ = true;
+ rtc_timer_.expires_from_now(std::chrono::milliseconds(1));
+ rtc_timer_.async_wait(
+ std::bind(&Impl::sendRTCContentObjectCallbackWithTrace, this,
+ std::placeholders::_1));
+ } else if (configuration_.input_stream_mode_) {
+ rtc_running_ = true;
+ // crate socket
+ remote_ = asio::ip::udp::endpoint(
+ asio::ip::address::from_string("127.0.0.1"), configuration_.port_);
+ socket_.open(asio::ip::udp::v4());
+ socket_.bind(remote_);
+ recv_buffer_.first = (uint8_t *)malloc(1500);
+ recv_buffer_.second = 1500;
+ receiveStream();
+ } else {
+ rtc_running_ = true;
+ rtc_timer_.expires_from_now(
+ configuration_.production_rate_.getMicrosecondsForPacket(
+ configuration_.payload_size_));
+ rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback,
+ this, std::placeholders::_1));
+ }
+#else
+ rtc_timer_.expires_from_now(
+ configuration_.production_rate_.getMicrosecondsForPacket(
+ configuration_.payload_size_));
+ rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback, this,
+ std::placeholders::_1));
+#endif
+ }
+
+ io_service_.run();
+
+ return ERROR_SUCCESS;
+ }
+
+ private:
+ hiperf::ServerConfiguration configuration_;
+ asio::io_service io_service_;
+ asio::signal_set signals_;
+ asio::steady_timer rtc_timer_;
+ std::vector<uint32_t> unsatisfied_interests_;
+ std::vector<std::shared_ptr<ContentObject>> content_objects_;
+ std::uint16_t content_objects_index_;
+ std::uint16_t mask_;
+ std::uint32_t last_segment_;
+ std::uint32_t *ptr_last_segment_;
+ std::unique_ptr<ProducerSocket> producer_socket_;
+#ifndef _WIN32
+ asio::posix::stream_descriptor input_;
+ asio::streambuf input_buffer_;
+ bool rtc_running_;
+ Name flow_name_;
+ asio::ip::udp::socket socket_;
+ asio::ip::udp::endpoint remote_;
+ std::pair<uint8_t *, std::size_t> recv_buffer_;
+#endif
+};
+
+HIperfServer::HIperfServer(const ServerConfiguration &conf) {
+ impl_ = new Impl(conf);
+}
+
+HIperfServer::~HIperfServer() { delete impl_; }
+
+int HIperfServer::setup() { return impl_->setup(); }
+
+void HIperfServer::run() { impl_->run(); }
+
+} // namespace hiperf
diff --git a/libtransport/includes/hicn/transport/security/crypto_hash_type.h b/apps/hiperf/src/server.h
index b7597e208..05407a807 100644
--- a/libtransport/includes/hicn/transport/security/crypto_hash_type.h
+++ b/apps/hiperf/src/server.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -15,17 +15,20 @@
#pragma once
-extern "C" {
-#include <parc/security/parc_CryptoHashType.h>
-};
+#include <common.h>
+
+namespace hiperf {
-namespace utils {
+class HIperfServer {
+ public:
+ HIperfServer(const ServerConfiguration &conf);
+ ~HIperfServer();
+ int setup();
+ void run();
-enum class CryptoHashType : uint8_t {
- SHA_256 = PARCCryptoHashType_SHA256,
- SHA_512 = PARCCryptoHashType_SHA512,
- CRC32C = PARCCryptoHashType_CRC32C,
- NULL_HASH = PARCCryptoHashType_NULL
+ private:
+ class Impl;
+ Impl *impl_;
};
-} \ No newline at end of file
+} // namespace hiperf \ No newline at end of file
diff --git a/apps/http-proxy/CMakeLists.txt b/apps/http-proxy/CMakeLists.txt
index 8c2043c30..66b9c1bab 100644
--- a/apps/http-proxy/CMakeLists.txt
+++ b/apps/http-proxy/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 14)
# -Wno-c99-designator issue
@@ -56,10 +56,18 @@ list(APPEND COMPILER_DEFINITIONS
-DWITH_POLICY
)
+list(APPEND HTTP_PROXY_LIBRARIES
+ ${LIBTRANSPORT_LIBRARIES}
+ ${LIBHICNCTRL_LIBRARIES}
+ ${LIBHICN_LIBRARIES}
+ ${OPENSSL_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
+)
+
build_library(${LIBHTTP_PROXY}
STATIC
SOURCES ${LIB_SOURCE_FILES}
- LINK_LIBRARIES ${LIBRARIES}
+ LINK_LIBRARIES ${HTTP_PROXY_LIBRARIES}
DEPENDS ${DEPENDENCIES}
INSTALL_HEADERS ${LIBPROXY_TO_INSTALL_HEADER_FILES}
INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBHICNCTRL_INCLUDE_DIRS} ${LIBPROXY_INCLUDE_DIRS}
diff --git a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
index 75cbbd64b..5cc80a168 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
+++ b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/forwarder_config.h
${CMAKE_CURRENT_SOURCE_DIR}/forwarder_interface.h
diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
index 19c96a9e3..e02b9d9a7 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
@@ -27,7 +27,6 @@
#include "forwarder_interface.h"
-
#define RETRY_INTERVAL 300
namespace transport {
@@ -68,7 +67,8 @@ class ForwarderConfig {
if (ret < 0) {
// We were not able to connect to the local forwarder. Do not give up
// and retry.
- TRANSPORT_LOGE("Could not connect to local forwarder. Retrying.");
+ TRANSPORT_LOG_ERROR
+ << "Could not connect to local forwarder. Retrying.";
timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
timer_.async_wait(std::bind(&ForwarderConfig::doTryToConnectToForwarder,
@@ -79,7 +79,8 @@ class ForwarderConfig {
doGetMainListener(std::make_error_code(std::errc(0)));
}
} else {
- TRANSPORT_LOGD("Timer for re-trying forwarder connection canceled.");
+ TRANSPORT_LOG_ERROR
+ << "Timer for re-trying forwarder connection canceled.";
}
}
@@ -90,9 +91,9 @@ class ForwarderConfig {
if (ret <= 0) {
// Since without the main listener of the forwarder the proxy cannot
// work, we can stop the program here until we get the listener port.
- TRANSPORT_LOGE(
- "Could not retrieve main listener port from the forwarder. "
- "Retrying.");
+ TRANSPORT_LOG_ERROR
+ << "Could not retrieve main listener port from the forwarder. "
+ "Retrying.";
timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
timer_.async_wait(std::bind(&ForwarderConfig::doGetMainListener, this,
@@ -104,7 +105,8 @@ class ForwarderConfig {
listener_retrieved_callback_(std::make_error_code(std::errc(0)));
}
} else {
- TRANSPORT_LOGI("Timer for retrieving main hicn listener canceled.");
+ TRANSPORT_LOG_ERROR
+ << "Timer for retrieving main hicn listener canceled.";
}
}
diff --git a/apps/http-proxy/src/forwarder_interface.cc b/apps/http-proxy/src/forwarder_interface.cc
index 7d8235ac6..c2448de9a 100644
--- a/apps/http-proxy/src/forwarder_interface.cc
+++ b/apps/http-proxy/src/forwarder_interface.cc
@@ -119,7 +119,7 @@ void ForwarderInterface::internalRemoveConnectedUser(uint32_t route_id) {
for (unsigned i = 0; i < routes_to_remove.size(); i++) {
connids_to_remove.insert(routes_to_remove[i]->face_id);
if (hc_route_delete(sock_, routes_to_remove[i]) < 0) {
- TRANSPORT_LOGE("Error removing route from forwarder.");
+ TRANSPORT_LOG_ERROR << "Error removing route from forwarder.";
}
}
@@ -146,7 +146,7 @@ void ForwarderInterface::internalRemoveConnectedUser(uint32_t route_id) {
for (unsigned i = 0; i < conns_to_remove.size(); i++) {
if (hc_connection_delete(sock_, conns_to_remove[i]) < 0) {
- TRANSPORT_LOGE("Error removing connection from forwarder.");
+ TRANSPORT_LOG_ERROR << "Error removing connection from forwarder.";
}
}
diff --git a/apps/http-proxy/src/http_proxy.cc b/apps/http-proxy/src/http_proxy.cc
index 262fcb8e1..2040f7cfa 100644
--- a/apps/http-proxy/src/http_proxy.cc
+++ b/apps/http-proxy/src/http_proxy.cc
@@ -67,8 +67,8 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
std::string remote_address =
socket.remote_endpoint().address().to_string();
std::uint16_t remote_port = socket.remote_endpoint().port();
- TRANSPORT_LOGD("Client %s:%d disconnected.", remote_address.c_str(),
- remote_port);
+ TRANSPORT_LOG_INFO << "Client " << remote_address << ":"
+ << remote_port << "disconnected.";
} catch (std::system_error& e) {
// Do nothing
}
@@ -85,7 +85,7 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
private:
void consumeNextRequest() {
if (request_buffer_queue_.size() == 0) {
- TRANSPORT_LOGD("No additional requests to process.");
+ // No additional requests to process
return;
}
@@ -136,24 +136,24 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
current_size_ += size;
if (is_last) {
- TRANSPORT_LOGD("Request received: %s",
- std::string((const char*)tmp_buffer_.first->data(),
- tmp_buffer_.first->length())
- .c_str());
+ // TRANSPORT_LOGD("Request received: %s",
+ // std::string((const char*)tmp_buffer_.first->data(),
+ // tmp_buffer_.first->length())
+ // .c_str());
if (current_size_ < 1400) {
request_buffer_queue_.emplace_back(std::move(tmp_buffer_));
} else {
- TRANSPORT_LOGE("Ignoring client request due to size (%zu) > 1400.",
- current_size_);
+ TRANSPORT_LOG_ERROR << "Ignoring client request due to size ("
+ << current_size_ << ") > 1400.";
session_->close();
current_size_ = 0;
return;
}
if (!consumer_.isRunning()) {
- TRANSPORT_LOGD(
- "Consumer stopped, triggering consume from TCP session "
- "handler..");
+ TRANSPORT_LOG_INFO
+ << "Consumer stopped, triggering consume from TCP session "
+ "handler..";
consumeNextRequest();
}
@@ -187,12 +187,13 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
void readBufferAvailable(std::unique_ptr<utils::MemBuf>&& buffer) noexcept {
// Response received. Send it back to client
auto _buffer = buffer.release();
- TRANSPORT_LOGD("From hicn: %zu bytes.", _buffer->length());
+ // TRANSPORT_LOGD("From hicn: %zu bytes.", _buffer->length());
session_->send(_buffer, []() {});
}
void readError(const std::error_code ec) noexcept {
- TRANSPORT_LOGE("Error reading from hicn consumer socket. Closing session.");
+ TRANSPORT_LOG_ERROR
+ << "Error reading from hicn consumer socket. Closing session.";
session_->close();
}
@@ -209,15 +210,14 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
* Let's grant it!
*/
if (metadata->method == "OPTIONS") {
- session_->send(
- (const uint8_t*)HTTPMessageFastParser::http_cors,
- std::strlen(HTTPMessageFastParser::http_cors), [this]() {
- auto& socket = session_->socket_;
- TRANSPORT_LOGI(
- "Sent OPTIONS to client %s:%d",
- socket.remote_endpoint().address().to_string().c_str(),
- socket.remote_endpoint().port());
- });
+ session_->send((const uint8_t*)HTTPMessageFastParser::http_cors,
+ std::strlen(HTTPMessageFastParser::http_cors), [this]() {
+ auto& socket = session_->socket_;
+ TRANSPORT_LOG_INFO
+ << "Sent OPTIONS to client "
+ << socket.remote_endpoint().address() << ":"
+ << socket.remote_endpoint().port();
+ });
}
} else {
tcp_receiver_.parseHicnHeader(
@@ -230,14 +230,14 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
}
/* Route created. Send back a 200 OK to client */
- session_->send(
- (const uint8_t*)reply, std::strlen(reply), [this, result]() {
- auto& socket = session_->socket_;
- TRANSPORT_LOGI(
- "Sent %d response to client %s:%d", result,
- socket.remote_endpoint().address().to_string().c_str(),
- socket.remote_endpoint().port());
- });
+ session_->send((const uint8_t*)reply, std::strlen(reply),
+ [this, result]() {
+ auto& socket = session_->socket_;
+ TRANSPORT_LOG_INFO
+ << "Sent " << result << " response to client "
+ << socket.remote_endpoint().address() << ":"
+ << socket.remote_endpoint().port();
+ });
});
}
}
@@ -313,7 +313,6 @@ void TcpReceiver::onClientDisconnect(HTTPClientConnectionCallback* client) {
void TcpReceiver::onNewConnection(asio::ip::tcp::socket&& socket) {
if (http_clients_.size() == 0) {
// Create new HTTPClientConnectionCallback
- TRANSPORT_LOGD("Creating new HTTPClientConnectionCallback.");
http_clients_.emplace_back(
new HTTPClientConnectionCallback(*this, thread_));
}
@@ -332,7 +331,8 @@ void TcpReceiver::onNewConnection(asio::ip::tcp::socket&& socket) {
void HTTPProxy::setupSignalHandler() {
signals_.async_wait([this](const std::error_code& ec, int signal_number) {
if (!ec) {
- TRANSPORT_LOGI("Received signal %d. Stopping gracefully.", signal_number);
+ TRANSPORT_LOG_INFO << "Received signal " << signal_number
+ << ". Stopping gracefully.";
stop();
}
});
diff --git a/apps/http-proxy/src/http_session.cc b/apps/http-proxy/src/http_session.cc
index 6b91c12c3..84c814cbd 100644
--- a/apps/http-proxy/src/http_session.cc
+++ b/apps/http-proxy/src/http_session.cc
@@ -111,7 +111,6 @@ void HTTPSession::send(utils::MemBuf *buffer,
doWrite();
}
} else {
- TRANSPORT_LOGD("Tell the handle connect it has data to write");
data_available_ = true;
}
});
@@ -134,15 +133,11 @@ void HTTPSession::doWrite() {
asio::async_write(socket_, asio::buffer(buffer->data(), buffer->length()),
[this](std::error_code ec, std::size_t length) {
if (TRANSPORT_EXPECT_FALSE(!ec)) {
- TRANSPORT_LOGD("Content successfully sent! %zu",
- length);
write_msgs_.front().second();
write_msgs_.pop_front();
if (!write_msgs_.empty()) {
doWrite();
}
- } else {
- TRANSPORT_LOGD("Content NOT sent!");
}
});
} // namespace transport
@@ -274,7 +269,7 @@ void HTTPSession::doReadHeader() {
void HTTPSession::tryReconnection() {
if (on_connection_closed_callback_(socket_)) {
if (state_ == ConnectorState::CONNECTED) {
- TRANSPORT_LOGD("Connection lost. Trying to reconnect...\n");
+ TRANSPORT_LOG_ERROR << "Connection lost. Trying to reconnect...";
state_ = ConnectorState::CONNECTING;
is_reconnection_ = true;
io_service_.post([this]() {
@@ -290,35 +285,35 @@ void HTTPSession::tryReconnection() {
}
void HTTPSession::doConnect() {
- asio::async_connect(socket_, endpoint_iterator_,
- [this](std::error_code ec, tcp::resolver::iterator) {
- if (!ec) {
- timer_.cancel();
- state_ = ConnectorState::CONNECTED;
+ asio::async_connect(
+ socket_, endpoint_iterator_,
+ [this](std::error_code ec, tcp::resolver::iterator) {
+ if (!ec) {
+ timer_.cancel();
+ state_ = ConnectorState::CONNECTED;
- asio::ip::tcp::no_delay noDelayOption(true);
- socket_.set_option(noDelayOption);
+ asio::ip::tcp::no_delay noDelayOption(true);
+ socket_.set_option(noDelayOption);
- // on_reconnect_callback_();
+ // on_reconnect_callback_();
- doReadHeader();
+ doReadHeader();
- if (data_available_ && !write_msgs_.empty()) {
- data_available_ = false;
- doWrite();
- }
+ if (data_available_ && !write_msgs_.empty()) {
+ data_available_ = false;
+ doWrite();
+ }
- if (is_reconnection_) {
- is_reconnection_ = false;
- TRANSPORT_LOGD("Connection recovered!");
- }
+ if (is_reconnection_) {
+ is_reconnection_ = false;
+ TRANSPORT_LOG_INFO << "Connection recovered!";
+ }
- } else {
- TRANSPORT_LOGE("Impossible to reconnect: %s",
- ec.message().c_str());
- close();
- }
- });
+ } else {
+ TRANSPORT_LOG_ERROR << "Impossible to reconnect: " << ec.message();
+ close();
+ }
+ });
}
bool HTTPSession::checkConnected() {
@@ -335,7 +330,7 @@ void HTTPSession::handleDeadline(const std::error_code &ec) {
if (!ec) {
io_service_.post([this]() {
socket_.close();
- TRANSPORT_LOGE("Error connecting. Is the server running?\n");
+ TRANSPORT_LOG_ERROR << "Error connecting. Is the server running?";
io_service_.stop();
});
}
diff --git a/apps/http-proxy/src/icn_receiver.cc b/apps/http-proxy/src/icn_receiver.cc
index 23e5b5623..ea8ac7191 100644
--- a/apps/http-proxy/src/icn_receiver.cc
+++ b/apps/http-proxy/src/icn_receiver.cc
@@ -55,28 +55,28 @@ AsyncConsumerProducer::AsyncConsumerProducer(
interface::GeneralTransportOptions::OUTPUT_BUFFER_SIZE, cache_size_);
if (ret != SOCKET_OPTION_SET) {
- TRANSPORT_LOGD("Warning: output buffer size has not been set.");
+ TRANSPORT_LOG_WARNING << "Warning: output buffer size has not been set.";
}
ret = producer_socket_.setSocketOption(
interface::GeneralTransportOptions::MAKE_MANIFEST, manifest);
if (ret != SOCKET_OPTION_SET) {
- TRANSPORT_LOGD("Warning: impossible to enable signatures.");
+ TRANSPORT_LOG_WARNING << "Warning: impossible to enable signatures.";
}
ret = producer_socket_.setSocketOption(
interface::GeneralTransportOptions::DATA_PACKET_SIZE, mtu_);
if (ret != SOCKET_OPTION_SET) {
- TRANSPORT_LOGD("Warning: mtu has not been set.");
+ TRANSPORT_LOG_WARNING << "Warning: mtu has not been set.";
}
producer_socket_.registerPrefix(prefix_);
}
void AsyncConsumerProducer::start() {
- TRANSPORT_LOGD("Starting listening");
+ TRANSPORT_LOG_INFO << "Starting listening";
doReceive();
}
@@ -90,8 +90,8 @@ void AsyncConsumerProducer::run() {
void AsyncConsumerProducer::stop() {
io_service_.post([this]() {
- TRANSPORT_LOGI("Number of requests processed by plugin: %lu",
- (unsigned long)request_counter_);
+ TRANSPORT_LOG_INFO << "Number of requests processed by plugin: "
+ << request_counter_;
producer_socket_.stop();
connector_.close();
});
@@ -123,16 +123,14 @@ void AsyncConsumerProducer::manageIncomingInterest(
if (_it != _end) {
if (_it->second.second) {
- TRANSPORT_LOGD(
- "Content is in production, interests will be satisfied shortly.");
return;
}
if (seg >= _it->second.first) {
- TRANSPORT_LOGD(
- "Ignoring interest with name %s for a content object which does not "
- "exist. (Request: %u, max: %u)",
- name.toString().c_str(), (uint32_t)seg, (uint32_t)_it->second.first);
+ // TRANSPORT_LOGD(
+ // "Ignoring interest with name %s for a content object which does not "
+ // "exist. (Request: %u, max: %u)",
+ // name.toString().c_str(), (uint32_t)seg, (uint32_t)_it->second.first);
return;
}
}
@@ -170,7 +168,7 @@ void AsyncConsumerProducer::publishContent(const uint8_t* data,
options.getLifetime());
if (TRANSPORT_EXPECT_FALSE(ret != SOCKET_OPTION_SET)) {
- TRANSPORT_LOGD("Warning: content object lifetime has not been set.");
+ TRANSPORT_LOG_WARNING << "Warning: content object lifetime has not been set.";
}
const interface::Name& name = options.getName();
diff --git a/utils/.clang-format b/apps/ping/.clang-format
index cd21e2017..cd21e2017 100644
--- a/utils/.clang-format
+++ b/apps/ping/.clang-format
diff --git a/apps/ping/CMakeLists.txt b/apps/ping/CMakeLists.txt
new file mode 100644
index 000000000..42f7f98c1
--- /dev/null
+++ b/apps/ping/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if (NOT DISABLE_EXECUTABLES)
+ list (APPEND PING_LIBRARIES
+ ${LIBTRANSPORT_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${WSOCK32_LIBRARY}
+ ${WS2_32_LIBRARY}
+ )
+
+ build_executable(hicn-ping-server
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_server.cc
+ LINK_LIBRARIES ${PING_LIBRARIES}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${HICN_APPS}
+ LINK_FLAGS ${LINK_FLAGS}
+ )
+
+ build_executable(hicn-ping-client
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_client.cc
+ LINK_LIBRARIES ${PING_LIBRARIES}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${HICN_APPS}
+ LINK_FLAGS ${LINK_FLAGS}
+ )
+endif () \ No newline at end of file
diff --git a/utils/src/ping_client.cc b/apps/ping/src/ping_client.cc
index e7a9228f2..24e0bf3ed 100644
--- a/utils/src/ping_client.cc
+++ b/apps/ping/src/ping_client.cc
@@ -13,18 +13,10 @@
* limitations under the License.
*/
+#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/core/global_object_pool.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/interfaces/portal.h>
-#include <hicn/transport/auth/verifier.h>
-#include <hicn/transport/utils/log.h>
-
-// Let's make the linker happy
-#if !TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
-#ifndef TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL
-TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = 0;
-#endif
-#endif
#include <asio/signal_set.hpp>
#include <asio/steady_timer.hpp>
@@ -105,7 +97,7 @@ class Client : interface::Portal::ConsumerCallback {
received_ = 0;
timedout_ = 0;
if (!c->certificate_.empty()) {
- verifier_.setCertificate(c->certificate_);
+ verifier_.useCertificate(c->certificate_);
}
}
@@ -189,14 +181,14 @@ class Client : interface::Portal::ConsumerCallback {
}
}
- void onTimeout(Interest::Ptr &&interest) override {
+ void onTimeout(Interest::Ptr &interest, const Name &name) override {
if (config_->verbose_) {
- std::cout << "### timeout for " << interest->getName()
+ std::cout << "### timeout for " << name
<< " src port: " << interest->getSrcPort()
<< " dst port: " << interest->getDstPort()
<< " flags: " << interest->printFlags() << std::endl;
} else if (!config_->quiet_) {
- std::cout << "### timeout for " << interest->getName() << std::endl;
+ std::cout << "### timeout for " << name << std::endl;
}
if (config_->dump_) {
diff --git a/utils/src/ping_server.cc b/apps/ping/src/ping_server.cc
index 79c662231..baf9c6698 100644
--- a/utils/src/ping_server.cc
+++ b/apps/ping/src/ping_server.cc
@@ -21,10 +21,10 @@
#include <openssl/applink.c>
#endif
-#include <hicn/transport/core/content_object.h>
-#include <hicn/transport/core/interest.h>
#include <hicn/transport/auth/identity.h>
#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/interest.h>
#include <hicn/transport/utils/string_tokenizer.h>
#include <asio.hpp>
@@ -291,7 +291,7 @@ int main(int argc, char **argv) {
CallbackContainer *stubs;
auth::Identity identity = setProducerIdentity(
- keystore_path, keystore_password, auth::CryptoHashType::SHA_256);
+ keystore_path, keystore_password, auth::CryptoHashType::SHA256);
if (sign) {
stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags,
diff --git a/cmake/Modules/BuildMacros.cmake b/cmake/Modules/BuildMacros.cmake
index c57aaa73c..2c301db5c 100644
--- a/cmake/Modules/BuildMacros.cmake
+++ b/cmake/Modules/BuildMacros.cmake
@@ -33,6 +33,7 @@ macro(build_executable exec)
PROPERTIES
OUTPUT_NAME ${exec}
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
+ BUILD_RPATH "${BUILD_ROOT}/lib"
INSTALL_RPATH_USE_LINK_PATH TRUE
ARCHIVE_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
LIBRARY_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
@@ -49,7 +50,7 @@ macro(build_executable exec)
endif()
if (ARG_COMPILE_OPTIONS)
- target_compile_options(${exec}-bin ${ARG_COMPILE_OPTIONS})
+ target_compile_options(${exec}-bin PRIVATE -Wall -Werror ${ARG_COMPILE_OPTIONS})
endif()
if(ARG_DEFINITIONS)
@@ -77,7 +78,7 @@ macro(build_library lib)
cmake_parse_arguments(ARG
"SHARED;STATIC;NO_DEV"
"COMPONENT;"
- "SOURCES;LINK_LIBRARIES;INSTALL_HEADERS;DEPENDS;INCLUDE_DIRS;DEFINITIONS;HEADER_ROOT_DIR;LIBRARY_ROOT_DIR;INSTALL_FULL_PATH_DIR;EMPTY_PREFIX;COMPILE_OPTIONS;VERSION"
+ "SOURCES;LINK_LIBRARIES;OBJECT_LIBRARIES;LINK_FLAGS;INSTALL_HEADERS;DEPENDS;INCLUDE_DIRS;DEFINITIONS;HEADER_ROOT_DIR;LIBRARY_ROOT_DIR;INSTALL_FULL_PATH_DIR;EMPTY_PREFIX;COMPILE_OPTIONS;VERSION"
${ARGN}
)
@@ -90,14 +91,14 @@ macro(build_library lib)
list(APPEND TARGET_LIBS
${lib}.shared
)
- add_library(${lib}.shared SHARED ${ARG_SOURCES})
+ add_library(${lib}.shared SHARED ${ARG_SOURCES} ${ARG_OBJECT_LIBRARIES})
endif()
if(ARG_STATIC)
list(APPEND TARGET_LIBS
${lib}.static
)
- add_library(${lib}.static STATIC ${ARG_SOURCES})
+ add_library(${lib}.static STATIC ${ARG_SOURCES} ${ARG_OBJECT_LIBRARIES})
endif()
if(NOT ARG_COMPONENT)
@@ -119,20 +120,24 @@ macro(build_library lib)
set_target_properties(${library}
PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
+ BUILD_RPATH "${BUILD_ROOT}/lib"
INSTALL_RPATH_USE_LINK_PATH TRUE
PREFIX ""
ARCHIVE_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
LIBRARY_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
RUNTIME_OUTPUT_DIRECTORY "${BUILD_ROOT}/bin"
+ LINK_FLAGS "${ARG_LINK_FLAGS}"
)
else ()
set_target_properties(${library}
PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
+ BUILD_RPATH "${BUILD_ROOT}/lib"
INSTALL_RPATH_USE_LINK_PATH TRUE
ARCHIVE_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
LIBRARY_OUTPUT_DIRECTORY "${BUILD_ROOT}/lib"
RUNTIME_OUTPUT_DIRECTORY "${BUILD_ROOT}/bin"
+ LINK_FLAGS "${ARG_LINK_FLAGS}"
)
endif()
@@ -143,7 +148,9 @@ macro(build_library lib)
WINDOWS_EXPORT_ALL_SYMBOLS TRUE
)
else ()
- target_compile_options(${library} PRIVATE -Wall ${ARG_COMPILE_OPTIONS})
+ target_compile_options(${library}
+ PRIVATE -Wall -Werror ${ARG_COMPILE_OPTIONS}
+ )
set_target_properties(${library}
PROPERTIES
OUTPUT_NAME ${lib}
@@ -152,7 +159,7 @@ macro(build_library lib)
# library deps
if(ARG_LINK_LIBRARIES)
- target_link_libraries(${library} ${ARG_LINK_LIBRARIES})
+ target_link_libraries(${library} PUBLIC ${ARG_LINK_LIBRARIES})
endif()
if(ARG_DEFINITIONS)
@@ -249,7 +256,7 @@ macro (build_module module)
LINK_LIBRARIES ${ARG_LINK_LIBRARIES}
INSTALL_HEADERS ${ARG_INSTALL_HEADERS}
DEPENDS ${ARG_DEPENDS}
- COMPONENT lib${LIBTRANSPORT}
+ COMPONENT ${ARG_COMPONENT}
INCLUDE_DIRS ${ARG_INCLUDE_DIRS}
HEADER_ROOT_DIR ${ARG_HEADER_ROOT_DIR}
LIBRARY_ROOT_DIR ${ARG_LIBRARY_ROOT_DIR}
diff --git a/cmake/Modules/FindConfig.cmake b/cmake/Modules/FindConfig.cmake
deleted file mode 100644
index 11e764d21..000000000
--- a/cmake/Modules/FindConfig.cmake
+++ /dev/null
@@ -1,56 +0,0 @@
-set(LIBCONFIG_SEARCH_PATH_LIST
- ${LIBCONFIG_HOME}
- $ENV{LIBCONFIG_HOME}
- /usr/local
- /opt
- /usr
-)
-
-find_path(CONFIG_INCLUDE_DIR libconfig.h
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the libconfig include"
-)
-
-if (WIN32)
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- find_library(CONFIG_LIBRARY NAMES libconfig.lib
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x64
- DOC "Find the libconfig libraries"
- )
- elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
- find_library(CONFIG_LIBRARY NAMES libconfig.lib
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib/x32
- DOC "Find the libconfig libraries"
- )
- endif()
-else()
- find_library(CONFIG_LIBRARY NAMES config
- HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the libconfig libraries"
- )
-endif()
-
-
-IF (CONFIG_INCLUDE_DIR AND CONFIG_LIBRARY)
- SET(CONFIG_FOUND TRUE)
-ENDIF ( CONFIG_INCLUDE_DIR AND CONFIG_LIBRARY)
-
-IF (CONFIG_FOUND)
- IF (NOT CONFIG_FIND_QUIETLY)
- MESSAGE(STATUS "Found Config: ${CONFIG_LIBRARY}")
- ENDIF (NOT CONFIG_FIND_QUIETLY)
-ELSE(CONFIG_FOUND)
- IF (Config_FIND_REQUIRED)
- IF(NOT CONFIG_INCLUDE_DIR)
- MESSAGE(FATAL_ERROR "Could not find LibConfig header file!")
- ENDIF(NOT CONFIG_INCLUDE_DIR)
-
- IF(NOT CONFIG_LIBRARY)
- MESSAGE(FATAL_ERROR "Could not find LibConfig library file!")
- ENDIF(NOT CONFIG_LIBRARY)
- ENDIF (Config_FIND_REQUIRED)
-ENDIF (CONFIG_FOUND) \ No newline at end of file
diff --git a/cmake/Modules/FindLibFec.cmake b/cmake/Modules/FindLibFec.cmake
deleted file mode 100644
index f8b33ad6b..000000000
--- a/cmake/Modules/FindLibFec.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-set(LIBFEC_SEARCH_PATH_LIST
- ${LIBFEC_HOME}
- $ENV{DEPENDENCIES}
- $ENV{LIBFEC_HOME}
- /usr/local
- /opt
- /usr
- )
-
-find_path(LIBFEC_INCLUDE_DIR fec/version.h
- HINTS ${LIBFEC_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the LibFec includes" )
-
-find_library(LIBFEC_LIBRARY NAMES fec
- HINTS ${LIBFEC_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the LibFec libraries" )
-
-set(LIBFEC_LIBRARIES ${LIBFEC_LIBRARY})
-set(LIBFEC_INCLUDE_DIRS ${LIBFEC_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(LibFec DEFAULT_MSG LIBFEC_LIBRARY LIBFEC_INCLUDE_DIR) \ No newline at end of file
diff --git a/cmake/Modules/FindLibRely.cmake b/cmake/Modules/FindLibRely.cmake
deleted file mode 100644
index 4b8960041..000000000
--- a/cmake/Modules/FindLibRely.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-set(LIBRELY_SEARCH_PATH_LIST
- ${LIBRELY_HOME}
- $ENV{DEPENDENCIES}
- $ENV{LIBRELY_HOME}
- /usr/local
- /opt
- /usr
- )
-
-find_path(LIBRELY_INCLUDE_DIR rely/version.hpp
- HINTS ${LIBRELY_SEARCH_PATH_LIST}
- PATH_SUFFIXES include
- DOC "Find the LibRely includes" )
-
-find_library(LIBRELY_LIBRARY NAMES rely
- HINTS ${LIBRELY_SEARCH_PATH_LIST}
- PATH_SUFFIXES lib
- DOC "Find the LibRely libraries" )
-
-set(LIBRELY_LIBRARIES ${LIBRELY_LIBRARY})
-set(LIBRELY_INCLUDE_DIRS ${LIBRELY_INCLUDE_DIR})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(LibRely DEFAULT_MSG LIBRELY_LIBRARY LIBRELY_INCLUDE_DIR) \ No newline at end of file
diff --git a/cmake/Modules/FindLibconfig++.cmake b/cmake/Modules/FindLibconfig++.cmake
index 8dfc5fbe8..1636ae96a 100644
--- a/cmake/Modules/FindLibconfig++.cmake
+++ b/cmake/Modules/FindLibconfig++.cmake
@@ -40,5 +40,4 @@ set(LIBCONFIG_INCLUDE_DIRS ${LIBCONFIG_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libconfig++ LIBCONFIG_CPP_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
-
mark_as_advanced(LIBCONFIG_CPP_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
diff --git a/cmake/Modules/Packager.cmake b/cmake/Modules/Packager.cmake
index f27479188..105952662 100644
--- a/cmake/Modules/Packager.cmake
+++ b/cmake/Modules/Packager.cmake
@@ -227,8 +227,11 @@ function(make_packages)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH /opt/hicn)
+
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+
set(CPACK_SET_DESTDIR true)
+
set(CMAKE_INSTALL_RPATH "\${CPACK_INSTALL_PREFIX}")
set(CMAKE_SKIP_INSTALL_RPATH FALSE)
set(HICN_DEPENDECIES_INSTALLER "${LIBTRANSPORT_LIBRARIES_LIST};${FACEMGR_LIBRARY_LIST};${APPS_LIBRARY_LIST}")
@@ -248,72 +251,85 @@ function(make_packages)
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_REVISION}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "hICN Components")
+
set(CPACK_COMPONENTS_ALL dependencies ${HICN_UTILS} ${HICN_LIGHT} ${HICN_APPS} ${FACEMGR} lib${LIBTRANSPORT} ${LIBTRANSPORT}-dev lib${LIBHICN} ${LIBHICN}-dev ${HICN_UTILS}-dev ${HICN_LIGHT}-dev ${HICN_APPS}-dev ${FACEMGR}-dev)
set(CPACK_COMPONENT_DEPENDENCIES_DISPLAY_NAME "Dependencies")
- if (HICN_UTILS)
+ if (NOT "${HICN_UTILS}" STREQUAL "")
string(TOUPPER ${HICN_UTILS} HICN_UTILS_UPPERCASE)
+ string(TOUPPER ${HICN_UTILS}-dev HICN_UTILS_DEV_UPPERCASE)
set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_DISPLAY_NAME "hICN utils")
+ set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_DISPLAY_NAME "hicn utils headers")
set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_GROUP "Executables")
+ set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_GROUP "Headers")
set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_DISPLAY_NAME "hicn-apps headers")
- endif()
- string(TOUPPER ${HICN_LIGHT} HICN_LIGHT_UPPERCASE)
- if (HICN_APPS)
+ set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ endif ()
+
+ if (NOT "${HICN_LIGHT}" STREQUAL "")
+ string(TOUPPER ${HICN_LIGHT} HICN_LIGHT_UPPERCASE)
+ string(TOUPPER ${HICN_LIGHT}-dev HICN_LIGHT_DEV_UPPERCASE)
+ set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_DISPLAY_NAME "hICN light apps")
+ set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_DISPLAY_NAME "hicn-light headers")
+ set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_GROUP "Executables")
+ set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ endif ()
+
+ if (NOT "${HICN_APPS}" STREQUAL "")
string(TOUPPER ${HICN_APPS} HICN_APPS_UPPERCASE)
string(TOUPPER ${HICN_APPS}-dev HICN_APPS_DEV_UPPERCASE)
set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_DISPLAY_NAME "hICN apps")
+ set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_DISPLAY_NAME "hicn-apps headers")
+ set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_GROUP "Executables")
set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_GROUP "Headers")
set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_INSTALL_TYPES Full)
set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif()
- if (FACEMGR)
+ endif ()
+
+ if (NOT "${FACEMGR}" STREQUAL "")
string(TOUPPER ${FACEMGR} FACEMGR_UPPERCASE)
string(TOUPPER ${FACEMGR}-dev FACEMGR_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_DISPLAY_NAME "facemgr headers")
set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_DISPLAY_NAME "facemgr")
+ set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_DISPLAY_NAME "facemgr headers")
set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_GROUP "Executables")
set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_GROUP "Headers")
set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_INSTALL_TYPES Full)
set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_INSTALL_TYPES Full)
- endif()
- string(TOUPPER lib${LIBTRANSPORT} LIBTRANSPORT_UPPERCASE)
- string(TOUPPER ${LIBTRANSPORT}-dev LIBTRANSPORT_DEV_UPPERCASE)
- string(TOUPPER lib${LIBHICN} LIBHICN_UPPERCASE)
- string(TOUPPER ${LIBHICN}-dev LIBHICN_DEV_UPPERCASE)
- string(TOUPPER ${HICN_UTILS}-dev HICN_UTILS_DEV_UPPERCASE)
- string(TOUPPER ${HICN_LIGHT}-dev HICN_LIGHT_DEV_UPPERCASE)
- set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_DISPLAY_NAME "hICN light apps")
- set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_DISPLAY_NAME "libtransport libs")
- set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_DISPLAY_NAME "hicn libs")
- set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_DISPLAY_NAME "libtransport headers")
- set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_DISPLAY_NAME "hicn headers")
- set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_DISPLAY_NAME "hicn utils headers")
- set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_DISPLAY_NAME "hicn-light headers")
+ endif ()
+
+ if (NOT "${LIBTRANSPORT}" STREQUAL "")
+ string(TOUPPER lib${LIBTRANSPORT} LIBTRANSPORT_UPPERCASE)
+ string(TOUPPER ${LIBTRANSPORT}-dev LIBTRANSPORT_DEV_UPPERCASE)
+ set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_DISPLAY_NAME "libtransport libs")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_DISPLAY_NAME "libtransport headers")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_GROUP "Libraries")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ endif ()
+
+ if (NOT "${LIBHICN}" STREQUAL "")
+ string(TOUPPER lib${LIBHICN} LIBHICN_UPPERCASE)
+ string(TOUPPER ${LIBHICN}-dev LIBHICN_DEV_UPPERCASE)
+ set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_DISPLAY_NAME "hicn libs")
+ set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_DISPLAY_NAME "hicn headers")
+ set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_GROUP "Libraries")
+ set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ endif ()
+
set (CPACK_RESOURCE_FILE_LICENSE
"${PROJECT_SOURCE_DIR}/cmake/Modules/License.txt")
set(CPACK_COMPONENT_DEPENDENCIES_DESCRIPTION
"All dependency libreries")
- set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_GROUP "Executables")
- set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_GROUP "Executables")
- set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_GROUP "Libraries")
- set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_GROUP "Libraries")
- set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_GROUP "Headers")
- set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_GROUP "Headers")
set(CPACK_COMPONENT_DEPENDENCIES_GROUP "Dependencies")
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_EXPANDED ON)
set(CPACK_COMPONENT_GROUP_DEPENDENCIES_DESCRIPTION
"All dependency libreries")
set(CPACK_ALL_INSTALL_TYPES Full Developer)
set(CPACK_INSTALL_TYPE_FULL_DISPLAY_NAME "Everything")
- set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_INSTALL_TYPES Full)
- set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_INSTALL_TYPES Full)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_INSTALL_RPATH /opt/hicn)
diff --git a/ctrl/CMakeLists.txt b/ctrl/CMakeLists.txt
index 50357651f..331ae9078 100644
--- a/ctrl/CMakeLists.txt
+++ b/ctrl/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(ctrl)
diff --git a/ctrl/facemgr/CMakeLists.txt b/ctrl/facemgr/CMakeLists.txt
index ba9de9464..2fad5d839 100644
--- a/ctrl/facemgr/CMakeLists.txt
+++ b/ctrl/facemgr/CMakeLists.txt
@@ -15,7 +15,7 @@ if (APPLE)
# >= 3.13 - CMP0079 (only needed on Apple platform for conditionally linking Network.framwork to libfacemgr)
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
else()
- cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
endif()
project(facemgr)
diff --git a/ctrl/libhicnctrl/CMakeLists.txt b/ctrl/libhicnctrl/CMakeLists.txt
index b2c5975be..22f81401f 100644
--- a/ctrl/libhicnctrl/CMakeLists.txt
+++ b/ctrl/libhicnctrl/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(libhicnctrl)
@@ -36,13 +36,6 @@ set(CMAKE_MACOSX_RPATH ON)
set(LIBHICNCTRL hicnctrl)
-if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- set(LIBHICNCTRL ${LIBHICNCTRL}-memif)
- set(LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs")
- list(APPEND HICN_LIBRARIES ${HICNPLUGIN_LIBRARIES})
- list(APPEND HICN_LIBRARIES ${SAFE_VAPI_LIBRARIES})
-endif()
-
set(LIBHICNCTRL ${LIBHICNCTRL} CACHE INTERNAL "" FORCE)
set(LIBHICNCTRL_SHARED ${LIBHICNCTRL}.shared CACHE INTERNAL "" FORCE)
set(LIBHICNCTRL_STATIC ${LIBHICNCTRL}.static CACHE INTERNAL "" FORCE)
@@ -94,6 +87,7 @@ else()
endif()
set(LIBHICNCTRL_COMPONENT lib${LIBHICNCTRL})
+set (LIBHICNCTRL_COMPONENT_MODULES ${LIBHICNCTRL_COMPONENT}-modules)
add_subdirectory(includes)
add_subdirectory(src)
diff --git a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake b/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
index bf0a4d504..2851375be 100644
--- a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
+++ b/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
@@ -25,45 +25,32 @@ set(${LIBHICNCTRL_COMPONENT}-dev_DESCRIPTION
CACHE STRING "Description for deb/rpm package."
)
-if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- set(${LIBHICNCTRL_COMPONENT}_DEB_DEPENDENCIES
- ""
- CACHE STRING "Dependencies for deb/rpm package."
- )
-
- set(${LIBHICNCTRL_COMPONENT}-dev_DEB_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} (>= stable_version), hicn-plugin-dev (>= stable_version)"
- CACHE STRING "Dependencies for deb/rpm package."
- )
-
- set(${LIBHICNCTRL_COMPONENT}_RPM_DEPENDENCIES
- ""
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBHICNCTRL_COMPONENT}_DEB_DEPENDENCIES
+ ""
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(${LIBHICNCTRL_COMPONENT}-dev_RPM_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} >= stable_version, hicn-plugin-dev >= stable_version"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBHICNCTRL_COMPONENT}-dev_DEB_DEPENDENCIES
+ "${LIBHICNCTRL_COMPONENT} (>= stable_version)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
-else ()
- set(${LIBHICNCTRL_COMPONENT}_DEB_DEPENDENCIES
- ""
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBHICNCTRL_COMPONENT}_RPM_DEPENDENCIES
+ ""
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(${LIBHICNCTRL_COMPONENT}-dev_DEB_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} (>= stable_version)"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBHICNCTRL_COMPONENT}-dev_RPM_DEPENDENCIES
+ "${LIBHICNCTRL_COMPONENT} >= stable_version"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(${LIBHICNCTRL_COMPONENT}_RPM_DEPENDENCIES
- ""
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBHICNCTRL_COMPONENT_MODULES}_DEB_DEPENDENCIES
+ "hicn-plugin (>= stable_version)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(${LIBHICNCTRL_COMPONENT}-dev_RPM_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} >= stable_version"
- CACHE STRING "Dependencies for deb/rpm package."
+set(${LIBHICNCTRL_COMPONENT_MODULES}_RPM_DEPENDENCIES
+ "hicn-plugin >= stable_version"
+ CACHE STRING "Dependencies for deb/rpm package."
)
-endif() \ No newline at end of file
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index f92b39ff3..b5a968800 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -76,6 +76,16 @@
#define HOTFIXMARGIN 0
+/**
+ * \brief Defines the default size for the allocated data arrays holding the
+ * results of API calls.
+ *
+ * This size should not be too small to avoid wasting memoyy, but also not too
+ * big to avoid unnecessary realloc's. Later on this size is doubled at each
+ * reallocation.
+ */
+#define DEFAULT_SIZE_LOG 3
+
/* Helper for avoiding warnings about type-punning */
#ifndef UNION_CAST
#define UNION_CAST(x, destType) \
@@ -231,6 +241,12 @@ hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
/* This should be at least equal to the maximum packet size */
#define RECV_BUFLEN 8192
+typedef enum {
+ HICNLIGHT,
+ VPP,
+ UNDEFINED
+} forwarder_t;
+
/**
* \brief Holds the state of an hICN control socket
*/
@@ -241,13 +257,22 @@ typedef struct hc_sock_s hc_sock_t;
* \param [in] url - The URL to connect to.
* \return an hICN control socket
*/
-hc_sock_t *hc_sock_create_url(const char *url);
+hc_sock_t *
+hc_sock_create_url(const char * url);
+
+/**
+ * \brief Create an hICN control socket using the provided forwarder.
+ * \return an hICN control socket
+ */
+hc_sock_t *
+hc_sock_create_forwarder(forwarder_t forwarder);
/**
* \brief Create an hICN control socket using the default connection type.
* \return an hICN control socket
*/
-hc_sock_t *hc_sock_create(void);
+hc_sock_t *
+hc_sock_create(void);
/**
* \brief Frees an hICN control socket
@@ -382,11 +407,7 @@ int hc_sock_reset(hc_sock_t *s);
#define NULLTERM 1
#endif
-#ifdef HICN_VPP_PLUGIN
- #define INTERFACE_LEN 64
-#else
- #define INTERFACE_LEN IFNAMSIZ
-#endif
+#define INTERFACE_LEN 16
#define MAXSZ_HC_NAME_ SYMBOLIC_NAME_LEN
#define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index f5d3c49a3..f9934d70e 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -15,41 +15,25 @@ list(APPEND COMPILER_DEFINITIONS
"-DWITH_POLICY"
)
-set(HEADER_FILES
- api.h
- commands.h
- face.h
-)
-
-set(UTIL_HEADER_FILES
- face.h
-)
-
set(SOURCE_FILES
face.c
route.c
+ api.c
)
-if(BUILD_HICNPLUGIN)
- set(SOURCE_FILES
- ${SOURCE_FILES}
- hicn_plugin_api.c
- )
-else ()
- set(SOURCE_FILES
- ${SOURCE_FILES}
- api.c
- )
-endif()
+set(HEADER_FILES
+ api_private.h
+)
set(LIBRARIES
m
+ dl
${HICN_LIBRARIES}
)
set(INCLUDE_DIRS
- ./
- ../includes/
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../includes/
${HICN_INCLUDE_DIRS}
)
@@ -61,9 +45,17 @@ else ()
set(LINK_TYPE SHARED STATIC)
endif ()
+if (${CMAKE_SYSTEM_NAME} MATCHES Android)
+ list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_api.c
+ )
+else()
+ add_subdirectory(modules)
+endif()
+
build_library(${LIBHICNCTRL}
${LINK_TYPE}
- SOURCES ${SOURCE_FILES}
+ SOURCES ${SOURCE_FILES} ${HEADER_FILES}
INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
LINK_LIBRARIES ${LIBRARIES}
DEPENDS ${DEPENDENCIES}
@@ -74,7 +66,13 @@ build_library(${LIBHICNCTRL}
)
if (NOT DISABLE_EXECUTABLES)
- set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBRARIES ${LIBRARIES} ${LIBHICNCTRL_STATIC})
+ set(DEPENDENCIES ${LIBHICNCTRL_STATIC})
+ else ()
+ set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
+ set(DEPENDENCIES ${LIBHICNCTRL_SHARED})
+ endif ()
list(APPEND DAEMON_SRC
cli.c
@@ -83,7 +81,7 @@ if (NOT DISABLE_EXECUTABLES)
build_executable(${HICNCTRL}
SOURCES ${DAEMON_SRC}
LINK_LIBRARIES ${LIBRARIES}
- DEPENDS ${LIBHICNCTRL_SHARED}
+ DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBHICNCTRL_COMPONENT}
INCLUDE_DIRS ${INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 8dcb978e0..4bb66c784 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -18,155 +18,26 @@
* \brief Implementation of hICN control library API
*/
-#include <assert.h> // assert
-#include <math.h> // log2
-#include <stdbool.h>
-#include <stdio.h> // snprintf
-#include <string.h> // memmove, strcasecmp
-#include <sys/socket.h> // socket
-#include <unistd.h> // close, fcntl
-#include <fcntl.h> // fcntl
-#include <sys/types.h> // getpid
-#include <unistd.h> // getpid
-#ifdef __linux__
-#include <sys/syscall.h>
-#define gettid() syscall(SYS_gettid)
-#endif /* __linux__ */
-
-#include <hicn/ctrl/api.h>
-#include <hicn/ctrl/commands.h>
-#include <hicn/util/token.h>
#include <hicn/util/log.h>
-#include <hicn/util/map.h>
-#include <strings.h>
+#include "api_private.h"
-#define PORT 9695
+#include <math.h> // log2
+#include <dlfcn.h> // dlopen
-#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0)
-#define BOOLSTR(x) ((x) ? "true" : "false")
-/*
- * Internal state associated to a pending request
- */
-typedef struct {
- int seq;
- hc_data_t * data;
- /* Information used to process results */
- int size_in;
- int (*parse)(const u8 * src, u8 * dst);
-} hc_sock_request_t;
-
-/**
- * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
- * the header_control_message structure. The forwarder simply answers back the
- * original sequence number. We maintain a map of such sequence number to
- * outgoing queries so that replied can be demultiplexed and treated
- * appropriately.
- */
-TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
-TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, generic_snprintf);
-
-struct hc_sock_s {
- char * url;
- int fd;
-
- /* Partial receive buffer */
- u8 buf[RECV_BUFLEN];
- size_t roff; /**< Read offset */
- size_t woff; /**< Write offset */
-
- /*
- * Because received messages are potentially unbounded in size, we might not
- * guarantee that we can store a full packet before processing it. We must
- * implement a very simple state machine remembering the current parsing
- * status in order to partially process the packet.
- */
- size_t remaining;
- u32 send_id;
-
- /* Next sequence number to be used for requests */
- int seq;
-
- /* Request being parsed (NULL if none) */
- hc_sock_request_t * cur_request;
-
- bool async;
- hc_sock_map_t * map;
+/* /!\ Please update constants in public header file upon changes */
+const char * connection_state_str[] = {
+#define _(x) [HC_CONNECTION_STATE_ ## x] = STRINGIZE(x),
+foreach_connection_state
+#undef _
};
-
-hc_sock_request_t *
-hc_sock_request_create(int seq, hc_data_t * data, HC_PARSE parse)
-{
- assert(data);
-
- hc_sock_request_t * request = malloc(sizeof(hc_sock_request_t));
- if (!request)
- return NULL;
- request->seq = seq;
- request->data = data;
- request->parse = parse;
- return request;
-}
-
-void
-hc_sock_request_free(hc_sock_request_t * request)
-{
- free(request);
-}
-
-
-#if 0
-#ifdef __APPLE__
-#define RANDBYTE() (u8)(arc4random() & 0xFF)
-#else
-#define RANDBYTE() (u8)(random() & 0xFF)
-#endif
-#endif
-#define RANDBYTE() (u8)(rand() & 0xFF)
-
-/*
- * list was working with all seq set to 0, but it seems hicnLightControl uses
- * 1, and replies with the same seqno
- */
-#define HICN_CTRL_SEND_SEQ_INIT 1
-#define HICN_CTRL_RECV_SEQ_INIT 1
-
-#define MAX(x, y) ((x > y) ? x : y)
-
-/**
- * \brief Defines the default size for the allocated data arrays holding the
- * results of API calls.
- *
- * This size should not be too small to avoid wasting memoyy, but also not too
- * big to avoid unnecessary realloc's. Later on this size is doubled at each
- * reallocation.
- */
-#define DEFAULT_SIZE_LOG 3
-
-/**
- * In practise, we want to preserve enough room to store a full packet of
- * average expected size (say a header + N payload elements).
- */
-#define AVG_ELEMENTS (1 << DEFAULT_SIZE_LOG)
-#define AVG_BUFLEN sizeof(hc_msg_header_t) + AVG_ELEMENTS * sizeof(hc_msg_payload_t)
-
-/*
- * We should at least have buffer space allowing to store one processable unit
- * of data, either the header of the maximum possible payload
- */
-#define MIN_BUFLEN MAX(sizeof(hc_msg_header_t), sizeof(hc_msg_payload_t))
-
-static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
-
-/* /!\ Please update constants in header file upon changes */
+/* /!\ Please update constants in public header file upon changes */
const char * connection_type_str[] = {
#define _(x) [CONNECTION_TYPE_ ## x] = STRINGIZE(x),
foreach_connection_type
#undef _
};
-#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x)
-
hc_connection_type_t
connection_type_from_str(const char * str)
{
@@ -177,14 +48,14 @@ connection_type_from_str(const char * str)
else if (strcasecmp(str, "HICN") == 0)
return CONNECTION_TYPE_HICN;
else
- return CONNECTION_TYPE_UNDEFINED;
+ return CONNECTION_TYPE_UNDEFINED;
}
/* Conversions to shield lib user from heterogeneity */
#define IS_VALID_LIST_CONNECTIONS_TYPE(x) ((x >= CONN_GRE) && (x <= CONN_HICN))
-static const hc_connection_type_t map_from_list_connections_type[] = {
+const hc_connection_type_t map_from_list_connections_type[] = {
[CONN_GRE] = CONNECTION_TYPE_UNDEFINED,
[CONN_TCP] = CONNECTION_TYPE_TCP,
[CONN_UDP] = CONNECTION_TYPE_UDP,
@@ -193,17 +64,9 @@ static const hc_connection_type_t map_from_list_connections_type[] = {
[CONN_HICN] = CONNECTION_TYPE_HICN,
};
-typedef enum {
- ENCAP_TCP,
- ENCAP_UDP,
- ENCAP_ETHER,
- ENCAP_LOCAL,
- ENCAP_HICN
-} EncapType;
-
#define IS_VALID_LIST_LISTENERS_TYPE(x) ((x >= ENCAP_TCP) && (x <= ENCAP_HICN))
-static const hc_connection_type_t map_from_encap_type[] = {
+const hc_connection_type_t map_from_encap_type[] = {
[ENCAP_TCP] = CONNECTION_TYPE_TCP,
[ENCAP_UDP] = CONNECTION_TYPE_UDP,
[ENCAP_ETHER] = CONNECTION_TYPE_UNDEFINED,
@@ -211,13 +74,13 @@ static const hc_connection_type_t map_from_encap_type[] = {
[ENCAP_HICN] = CONNECTION_TYPE_HICN,
};
-static const connection_type map_to_connection_type[] = {
+const connection_type map_to_connection_type[] = {
[CONNECTION_TYPE_TCP] = TCP_CONN,
[CONNECTION_TYPE_UDP] = UDP_CONN,
[CONNECTION_TYPE_HICN] = HICN_CONN,
};
-static const listener_mode map_to_listener_mode[] = {
+const listener_mode map_to_listener_mode[] = {
[CONNECTION_TYPE_TCP] = IP_MODE,
[CONNECTION_TYPE_UDP] = IP_MODE,
[CONNECTION_TYPE_HICN] = HICN_MODE,
@@ -225,13 +88,6 @@ static const listener_mode map_to_listener_mode[] = {
#define IS_VALID_LIST_CONNECTIONS_STATE(x) ((x >= IFACE_UP) && (x <= IFACE_UNKNOWN))
-/* /!\ Please update constants in header file upon changes */
-const char * connection_state_str[] = {
-#define _(x) [HC_CONNECTION_STATE_ ## x] = STRINGIZE(x),
-foreach_connection_state
-#undef _
-};
-
/*
#define IS_VALID_CONNECTION_STATE(x) IS_VALID_ENUM_TYPE(CONNECTION_STATE, x)
@@ -242,19 +98,14 @@ static const connection_state map_to_connection_state[] = {
*/
-static const hc_connection_state_t map_from_list_connections_state[] = {
+const hc_connection_state_t map_from_list_connections_state[] = {
[IFACE_UP] = HC_CONNECTION_STATE_UP,
[IFACE_DOWN] = HC_CONNECTION_STATE_DOWN,
[IFACE_UNKNOWN] = HC_CONNECTION_STATE_UNDEFINED,
};
-#define connection_state_to_face_state(x) ((face_state_t)(x))
-#define face_state_to_connection_state(x) ((hc_connection_state_t)(x))
-
-#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX))
-
-static const int map_from_addr_type[] = {
+const int map_from_addr_type[] = {
[ADDR_INET] = AF_INET,
[ADDR_INET6] = AF_INET6,
[ADDR_LINK] = AF_UNSPEC,
@@ -262,49 +113,12 @@ static const int map_from_addr_type[] = {
[ADDR_UNIX] = AF_UNSPEC,
};
-static const address_type map_to_addr_type[] = {
+const address_type map_to_addr_type[] = {
[AF_INET] = ADDR_INET,
[AF_INET6] = ADDR_INET6,
};
/******************************************************************************
- * Message helper types and aliases
- ******************************************************************************/
-
-#define foreach_hc_command \
- _(add_connection) \
- _(remove_connection) \
- _(list_connections) \
- _(add_listener) \
- _(remove_listener) \
- _(list_listeners) \
- _(add_route) \
- _(remove_route) \
- _(list_routes) \
- _(cache_store) \
- _(cache_serve) \
- /*_(cache_clear) */ \
- _(set_strategy) \
- _(set_wldr) \
- _(add_punting) \
- _(mapme_activator) \
- _(mapme_timing)
-
-typedef header_control_message hc_msg_header_t;
-
-typedef union {
-#define _(x) x ## _command x;
- foreach_hc_command
-#undef _
-} hc_msg_payload_t;
-
-
-typedef struct hc_msg_s {
- hc_msg_header_t hdr;
- hc_msg_payload_t payload;
-} hc_msg_t;
-
-/******************************************************************************
* Control Data
******************************************************************************/
@@ -358,7 +172,8 @@ hc_data_ensure_available(hc_data_t * data, size_t count)
if (!data->buffer)
return -1;
}
- return 0;
+
+ return 0;
}
int
@@ -370,7 +185,8 @@ hc_data_push_many(hc_data_t * data, const void * elements, size_t count)
memcpy(data->buffer + data->size * data->out_element_size, elements,
count * data->out_element_size);
data->size += count;
- return 0;
+
+ return 0;
}
int
@@ -398,7 +214,7 @@ hc_data_set_callback(hc_data_t * data, data_callback_t cb, void * cb_data)
{
data->complete_cb = cb;
data->complete_cb_data = cb_data;
- return 0;
+ return 0;
}
int
@@ -408,7 +224,7 @@ hc_data_set_complete(hc_data_t * data)
data->ret = 0;
if (data->complete_cb)
return data->complete_cb(data, data->complete_cb_data);
- return 0;
+ return 0;
}
int
@@ -422,748 +238,164 @@ int
hc_data_reset(hc_data_t * data)
{
data->size = 0;
- return 0;
+ return 0;
}
-/******************************************************************************
- * Control socket
- ******************************************************************************/
-
-/**
- * \brief Parse a connection URL into a sockaddr
- * \param [in] url - URL
- * \param [out] sa - Resulting struct sockaddr, expected zero'ed.
- * \return 0 if parsing succeeded, a negative error value otherwise.
- */
-int
-hc_sock_parse_url(const char * url, struct sockaddr * sa)
+static hc_sock_t * _open_module(const char *name)
{
- /* FIXME URL parsing is currently not implemented */
- assert(!url);
-
-#ifdef __linux__
- srand(time(NULL) ^ getpid() ^ gettid());
+ char complete_name[128];
+#ifdef __APPLE__
+ sprintf(complete_name, "%s.dylib", name);
+#elif defined(__linux__)
+ sprintf(complete_name, "%s.so", name);
#else
- srand((unsigned int )(time(NULL) ^ getpid()));
-#endif /* __linux__ */
-
- /*
- * A temporary solution is to inspect the sa_family fields of the passed in
- * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP
- * connection to localhost.
- */
- switch (sa->sa_family) {
- case AF_UNSPEC:
- case AF_INET:
- {
- struct sockaddr_in * sai = (struct sockaddr_in *)sa;
- sai->sin_family = AF_INET;
- sai->sin_port = htons(PORT);
- sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- break;
- }
- case AF_INET6:
- {
- struct sockaddr_in6 * sai6 = (struct sockaddr_in6 *)sa;
- sai6->sin6_family = AF_INET6;
- sai6->sin6_port = htons(PORT);
- sai6->sin6_addr = loopback_addr;
- break;
- }
- default:
- return -1;
- }
-
- return 0;
-}
-
-hc_sock_t *
-hc_sock_create_url(const char * url)
-{
- hc_sock_t * s = malloc(sizeof(hc_sock_t));
- if (!s)
- goto ERR_MALLOC;
-
- s->url = url ? strdup(url) : NULL;
-
- s->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (s->fd < 0)
- goto ERR_SOCKET;
+ #error "System not supported for dynamic lynking"
+#endif
- if (hc_sock_reset(s) < 0)
- goto ERR_RESET;
+ void *handle = 0;
+ const char *error = 0;
+ hc_sock_t *(*creator)(void) = 0;
+ hc_sock_t *ret = 0;
- s->seq = 0;
- s->cur_request = NULL;
+ // open module
+ handle = dlopen(complete_name, RTLD_LAZY);
+ if (!handle) {
+ if ((error = dlerror()) != 0) {
+ ERROR("%s", error);
+ }
- s->map = hc_sock_map_create();
- if (!s->map)
- goto ERR_MAP;
+ return 0;
+ }
+
+ // get factory method
+ creator = (hc_sock_t * (*)(void)) dlsym(handle, "_hc_sock_create");
+ if (!creator) {
+ if ((error = dlerror()) != 0) {
+ ERROR("%s", error);
+ return 0;
+ }
+ }
- return s;
+ ret = (*creator)();
+ ret->handle = handle;
- //hc_sock_map_free(s->map);
-ERR_MAP:
-ERR_RESET:
- if (s->url)
- free(s->url);
- close(s->fd);
-ERR_SOCKET:
- free(s);
-ERR_MALLOC:
- return NULL;
+ return ret;
}
-hc_sock_t *
-hc_sock_create(void)
+hc_sock_t *hc_sock_create_forwarder(forwarder_t forwarder)
{
- return hc_sock_create_url(NULL);
-}
-
-void
-hc_sock_free(hc_sock_t * s)
-{
- hc_sock_request_t ** request_array = NULL;
- int n = hc_sock_map_get_value_array(s->map, &request_array);
- if (n < 0) {
- ERROR("Could not retrieve pending request array for freeing up resources");
- } else {
- for (unsigned i = 0; i < n; i++) {
- hc_sock_request_t * request = request_array[i];
- if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
- ERROR("[hc_sock_process] Error removing request from map");
- hc_sock_request_free(request);
- }
- free(request_array);
+ switch (forwarder)
+ {
+ case HICNLIGHT:
+ return _open_module("hicnlightctrl_module");
+ case VPP:
+ return _open_module("vppctrl_module");
+ default:
+ return NULL;
}
-
- hc_sock_map_free(s->map);
- if (s->url)
- free(s->url);
- close(s->fd);
- free(s);
}
-int
-hc_sock_get_next_seq(hc_sock_t * s)
-{
- return s->seq++;
-}
+#ifdef ANDROID
+// In android we do not load a module at runtime
+// but we link the hicnlight implmentation directly
+// to the main library
+extern hc_sock_t *_hc_sock_create();
+#endif
-int
-hc_sock_set_nonblocking(hc_sock_t * s)
+hc_sock_t *hc_sock_create(void)
{
- return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0);
-}
-
-int
-hc_sock_get_fd(hc_sock_t * s)
-{
- return s->fd;
+#ifdef ANDROID
+ hc_sock_t *ret = _hc_sock_create();
+ ret->handle = NULL;
+ return ret;
+#else
+ return hc_sock_create_forwarder(HICNLIGHT);
+#endif
}
-int
-hc_sock_connect(hc_sock_t * s)
+void hc_sock_free(hc_sock_t *s)
{
- struct sockaddr_storage ss;
- memset(&ss, 0, sizeof(struct sockaddr_storage));
-
- if (hc_sock_parse_url(s->url, (struct sockaddr *)&ss) < 0)
- goto ERR_PARSE;
-
- size_t size = ss.ss_family == AF_INET
- ? sizeof(struct sockaddr_in)
- : sizeof(struct sockaddr_in6);
- if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) //sizeof(struct sockaddr)) < 0)
- goto ERR_CONNECT;
+ void *handle = s->handle;
+ s->hc_sock_free(s);
- return 0;
-
-ERR_CONNECT:
-ERR_PARSE:
- return -1;
-}
-
-int
-hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen, int seq)
-{
- int rc;
- msg->hdr.seqNum = seq;
- rc = (int)send(s->fd, msg, msglen, 0);
- if (rc < 0) {
- perror("hc_sock_send");
- return -1;
+ if (handle) {
+ dlclose(handle);
}
- return 0;
}
-int
-hc_sock_get_available(hc_sock_t * s, u8 ** buffer, size_t * size)
+int hc_sock_get_next_seq(hc_sock_t *s)
{
- *buffer = s->buf + s->woff;
- *size = RECV_BUFLEN - s->woff;
-
- return 0;
+ return s->hc_sock_get_next_seq(s);
}
-int
-hc_sock_recv(hc_sock_t * s)
+int hc_sock_set_nonblocking(hc_sock_t *s)
{
- int rc;
-
- /*
- * This condition should be ensured to guarantee correct processing of
- * messages
- */
- assert(RECV_BUFLEN - s->woff > MIN_BUFLEN);
-
- rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0);
- if (rc == 0) {
- /* Connection has been closed */
- return 0;
- }
- if (rc < 0) {
- /*
- * Let's not return 0 which currently means the socket has been closed
- */
- if (errno == EWOULDBLOCK)
- return -1;
- perror("hc_sock_recv");
- return -1;
- }
- s->woff += rc;
- return rc;
+ return s->hc_sock_get_next_seq(s);
}
-/*
- * Returns -99 in case of internal error, -1 in case of API command failure
- */
-int
-hc_sock_process(hc_sock_t * s, hc_data_t ** data)
+int hc_sock_get_fd(hc_sock_t *s)
{
- int err = 0;
-
- /* We must have received at least one byte */
- size_t available = s->woff - s->roff;
-
- while(available > 0) {
-
- if (!s->cur_request) { // No message being parsed, alternatively (remaining == 0)
- hc_msg_t * msg = (hc_msg_t*)(s->buf + s->roff);
-
- /* We expect a message header */
- if (available < sizeof(hc_msg_header_t)) {
- break;
- }
-
- hc_sock_request_t * request = NULL;
- if (hc_sock_map_get(s->map, msg->hdr.seqNum, &request) < 0) {
- ERROR("[hc_sock_process] Error searching for matching request");
- return -99;
- }
- if (!request) {
- ERROR("[hc_sock_process] No request matching received sequence number");
- return -99;
- }
-
- s->remaining = msg->hdr.length;
- switch(msg->hdr.messageType) {
- case ACK_LIGHT:
- assert(s->remaining == 1);
- assert(!data);
- s->cur_request = request;
- break;
- case NACK_LIGHT:
- assert(s->remaining == 1);
- assert(!data);
- hc_data_set_error(request->data);
- s->cur_request = request;
- err = -1;
- break;
- case RESPONSE_LIGHT:
- assert(data);
- if (s->remaining == 0) {
- hc_data_set_complete(request->data);
- *data = request->data;
- if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
- ERROR("[hc_sock_process] Error removing request from map");
- hc_sock_request_free(request);
- } else {
- /* We only remember it if there is still data to parse */
- s->cur_request = request;
- }
- break;
- default:
- ERROR("[hc_sock_process] Invalid response received");
- return -99;
- }
-
- available -= sizeof(hc_msg_header_t);
- s->roff += sizeof(hc_msg_header_t);
- } else {
- /* We expect the complete payload, or at least a chunk of it */
- size_t num_chunks = available / s->cur_request->data->in_element_size;
- if (num_chunks == 0)
- break;
- if (num_chunks > s->remaining)
- num_chunks = s->remaining;
-
- if (!s->cur_request->parse) {
- /* If we don't need to parse results, then we can directly push
- * all of them into the result data structure */
- hc_data_push_many(s->cur_request->data, s->buf + s->roff, num_chunks);
- } else {
- int rc;
- rc = hc_data_ensure_available(s->cur_request->data, num_chunks);
- if (rc < 0) {
- ERROR("[hc_sock_process] Error in hc_data_ensure_available");
- return -99;
- }
- for (int i = 0; i < num_chunks; i++) {
- u8 * dst = hc_data_get_next(s->cur_request->data);
- if (!dst) {
- ERROR("[hc_sock_process] Error in hc_data_get_next");
- return -99;
- }
-
- rc = s->cur_request->parse(s->buf + s->roff + i * s->cur_request->data->in_element_size, dst);
- if (rc < 0) {
- ERROR("[hc_sock_process] Error in parse");
- err = -99; /* FIXME we let the loop complete (?) */
- }
- s->cur_request->data->size++;
- }
- }
-
- s->remaining -= num_chunks;
- available -= num_chunks * s->cur_request->data->in_element_size;
- s->roff += num_chunks * s->cur_request->data->in_element_size;
- if (s->remaining == 0) {
- if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
- ERROR("[hc_sock_process] Error removing request from map");
- return -99;
- }
- hc_data_set_complete(s->cur_request->data);
- if (data)
- *data = s->cur_request->data;
- hc_sock_request_free(s->cur_request);
- s->cur_request = NULL;
- }
-
- }
- }
-
- /* Make sure there is enough remaining space in the buffer */
- if (RECV_BUFLEN - s->woff < AVG_BUFLEN) {
- /*
- * There should be no overlap provided a sufficiently large BUFLEN, but
- * who knows.
- */
- memmove(s->buf, s->buf + s->roff, s->woff - s->roff);
- s->woff -= s->roff;
- s->roff = 0;
- }
-
- return err;
+ return s->hc_sock_get_fd(s);
}
-int
-hc_sock_callback(hc_sock_t * s, hc_data_t ** pdata)
-{
- hc_data_t * data;
-
- for (;;) {
- int n = hc_sock_recv(s);
- if (n == 0)
- goto ERR_EOF;
- if (n < 0) {
- switch(errno) {
- case ECONNRESET:
- case ENODEV:
- /* Forwarder restarted */
- WARN("Forwarder likely restarted: not (yet) implemented");
- goto ERR;
- case EWOULDBLOCK:
- //DEBUG("Would block... stop reading from socket");
- goto END;
- default:
- perror("hc_sock_recv");
- goto ERR;
- }
- }
- if (hc_sock_process(s, &data) < 0) {
- goto ERR;
- }
- }
-END:
- if (pdata)
- *pdata = data;
- else
- hc_data_free(data);
- return 0;
-
-ERR:
- hc_data_free(data);
-ERR_EOF:
- return -1;
-}
-
-int
-hc_sock_reset(hc_sock_t * s)
+int hc_sock_connect(hc_sock_t *s)
{
- s->roff = s->woff = 0;
- s->remaining = 0;
- return 0;
+ return s->hc_sock_connect(s);
}
-/******************************************************************************
- * Command-specific structures and functions
- ******************************************************************************/
-
-typedef int (*HC_PARSE)(const u8 *, u8 *);
-
-typedef struct {
- hc_action_t cmd;
- command_id cmd_id;
- size_t size_in;
- size_t size_out;
- HC_PARSE parse;
-} hc_command_params_t;
-
-int
-hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len,
- hc_command_params_t * params, hc_data_t ** pdata, bool async)
-{
- int ret;
- if (async)
- assert(!pdata);
-
- /* Sanity check */
- switch(params->cmd) {
- case ACTION_CREATE:
- assert(params->size_in != 0); /* payload repeated */
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- case ACTION_DELETE:
- assert(params->size_in != 0); /* payload repeated */
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- case ACTION_LIST:
- assert(params->size_in != 0);
- assert(params->size_out != 0);
- assert(params->parse != NULL);
- break;
- case ACTION_SET:
- assert(params->size_in != 0);
- assert(params->size_out == 0);
- assert(params->parse == NULL);
- break;
- default:
- return -1;
- }
-
- //hc_sock_reset(s);
-
- /* XXX data will at least store the result (complete) */
- hc_data_t * data = hc_data_create(params->size_in, params->size_out, NULL);
- if (!data) {
- ERROR("[hc_execute_command] Could not create data storage");
- goto ERR_DATA;
- }
-
- int seq = hc_sock_get_next_seq(s);
-
- /* Create state used to process the request */
- hc_sock_request_t * request = NULL;
- request = hc_sock_request_create(seq, data, params->parse);
- if (!request) {
- ERROR("[hc_execute_command] Could not create request state");
- goto ERR_REQUEST;
- }
-
- /* Add state to map */
- if (hc_sock_map_add(s->map, seq, request) < 0) {
- ERROR("[hc_execute_command] Error adding request state to map");
- goto ERR_MAP;
- }
-
- if (hc_sock_send(s, msg, msg_len, seq) < 0) {
- ERROR("[hc_execute_command] Error sending message");
- goto ERR_PROCESS;
- }
-
- if (async)
- return 0;
-
- while(!data->complete) {
- /*
- * As the socket is non blocking it might happen that we need to read
- * several times before success... shall we alternate between blocking
- * and non-blocking mode ?
- */
- int n = hc_sock_recv(s);
- if (n == 0)
- goto ERR_EOF;
- if (n < 0)
- continue; //break;
- int rc = hc_sock_process(s, pdata);
- switch(rc) {
- case 0:
- break;
- case -1:
- ret = rc;
- break;
- case -99:
- ERROR("[hc_execute_command] Error processing socket results");
- goto ERR;
- break;
- default:
- ERROR("[hc_execute_command] Unexpected return value");
- goto ERR;
- }
- }
-
-ERR_EOF:
- ret = data->ret;
- if (!data->complete)
- return -1;
- if (!pdata)
- hc_data_free(data);
-
- return ret;
-
-ERR_PROCESS:
-ERR_MAP:
- hc_sock_request_free(request);
-ERR:
-ERR_REQUEST:
- hc_data_free(data);
-ERR_DATA:
- return -99;
-}
-
-/*----------------------------------------------------------------------------*
- * Listeners
- *----------------------------------------------------------------------------*/
-
-/* LISTENER CREATE */
-
-int
-_hc_listener_create(hc_sock_t * s, hc_listener_t * listener, bool async)
+int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size)
{
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[_hc_listener_create] Unexpected truncation of listener string");
- DEBUG("[_hc_listener_create] listener=%s async=%s", listener_s,
- BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(listener->family))
- return -1;
-
- if (!IS_VALID_CONNECTION_TYPE(listener->type))
- return -1;
-
- struct {
- header_control_message hdr;
- add_listener_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_LISTENER,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = listener->local_addr,
- .port = htons(listener->local_port),
- .addressType = (u8)map_to_addr_type[listener->family],
- .listenerMode = (u8)map_to_listener_mode[listener->type],
- .connectionType = (u8)map_to_connection_type[listener->type],
- }
- };
-
- rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_create] Unexpected truncation of symbolic name string");
-
- rc = snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name);
- if (rc >= INTERFACE_LEN)
- WARN("[_hc_listener_create] Unexpected truncation of interface name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_LISTENER,
- .size_in = sizeof(add_listener_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+ return s->hc_sock_get_available(s, buffer, size);
}
-int
-hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
+int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq)
{
- return _hc_listener_create(s, listener, false);
+ return s->hc_sock_send(s, msg, msglen, seq);
}
-int
-hc_listener_create_async(hc_sock_t * s, hc_listener_t * listener)
+int hc_sock_recv(hc_sock_t *s)
{
- return _hc_listener_create(s, listener, true);
+ return s->hc_sock_recv(s);
}
-/* LISTENER GET */
-
-int
-hc_listener_get(hc_sock_t * s, hc_listener_t * listener,
- hc_listener_t ** listener_found)
+int hc_sock_process(hc_sock_t *s, hc_data_t **data)
{
- hc_data_t * listeners;
- hc_listener_t * found;
-
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[hc_listener_get] Unexpected truncation of listener string");
- DEBUG("[hc_listener_get] listener=%s", listener_s);
-
- if (hc_listener_list(s, &listeners) < 0)
- return -1;
-
- /* Test */
- if (hc_listener_find(listeners, listener, &found) < 0) {
- hc_data_free(listeners);
- return -1;
- }
-
- if (found) {
- *listener_found = malloc(sizeof(hc_listener_t));
- if (!*listener_found)
- return -1;
- **listener_found = *found;
- } else {
- *listener_found = NULL;
- }
-
- hc_data_free(listeners);
-
- return 0;
+ return s->hc_sock_process(s, data);
}
-
-/* LISTENER DELETE */
-
-int
-_hc_listener_delete(hc_sock_t * s, hc_listener_t * listener, bool async)
-{
- char listener_s[MAXSZ_HC_LISTENER];
- int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
- if (rc >= MAXSZ_HC_LISTENER)
- WARN("[_hc_listener_delete] Unexpected truncation of listener string");
- DEBUG("[_hc_listener_delete] listener=%s async=%s", listener_s,
- BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- remove_listener_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_LISTENER,
- .length = 1,
- .seqNum = 0,
- },
- };
-
- if (listener->id) {
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- } else if (*listener->name) {
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listener->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- } else {
- hc_listener_t * listener_found;
- if (hc_listener_get(s, listener, &listener_found) < 0)
- return -1;
- if (!listener_found)
- return -1;
- rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener_found->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
- free(listener_found);
- }
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_LISTENER,
- .size_in = sizeof(remove_listener_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+int hc_sock_callback(hc_sock_t *s, hc_data_t **data)
+{
+ return s->hc_sock_callback(s, data);
}
-int
-hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
+int hc_sock_reset(hc_sock_t *s)
{
- return _hc_listener_delete(s, listener, false);
+ return s->hc_sock_reset(s);
}
-int
-hc_listener_delete_async(hc_sock_t * s, hc_listener_t * listener)
+int hc_listener_create(hc_sock_t *s, hc_listener_t *listener)
{
- return _hc_listener_delete(s, listener, true);
+ return s->hc_listener_create(s, listener);
}
-
-/* LISTENER LIST */
-
-int
-_hc_listener_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
-{
- DEBUG("[hc_listener_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_LISTENERS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_LISTENERS,
- .size_in = sizeof(list_listeners_command),
- .size_out = sizeof(hc_listener_t),
- .parse = (HC_PARSE)hc_listener_parse,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+int hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
+ hc_listener_t **listener_found)
+{
+ return s->hc_listener_get(s, listener, listener_found);
}
-int
-hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
+int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener)
{
- return _hc_listener_list(s, pdata, false);
+ return s->hc_listener_delete(s, listener);
}
-int
-hc_listener_list_async(hc_sock_t * s, hc_data_t ** pdata)
+int hc_listener_list(hc_sock_t *s, hc_data_t **pdata)
{
- return _hc_listener_list(s, pdata, true);
+ return s->hc_listener_list(s, pdata);
}
+GENERATE_FIND(listener);
+
/* LISTENER VALIDATE */
int
@@ -1247,8 +479,6 @@ hc_listener_parse(void * in, hc_listener_t * listener)
return 0;
}
-GENERATE_FIND(listener)
-
/* LISTENER SNPRINTF */
/* /!\ Please update constants in header file upon changes */
@@ -1268,221 +498,57 @@ hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener)
connection_type_str[listener->type]);
}
-/*----------------------------------------------------------------------------*
- * CONNECTION
- *----------------------------------------------------------------------------*/
-
-/* CONNECTION CREATE */
-
-int
-_hc_connection_create(hc_sock_t * s, hc_connection_t * connection, bool async)
+int hc_connection_create(hc_sock_t *s, hc_connection_t *connection)
{
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[_hc_connection_create] Unexpected truncation of connection string");
- DEBUG("[_hc_connection_create] connection=%s async=%s", connection_s, BOOLSTR(async));
-
- if (hc_connection_validate(connection) < 0)
- return -1;
-
- struct {
- header_control_message hdr;
- add_connection_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_CONNECTION,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .remoteIp = connection->remote_addr,
- .localIp = connection->local_addr,
- .remotePort = htons(connection->remote_port),
- .localPort = htons(connection->local_port),
- .ipType = (u8)map_to_addr_type[connection->family],
- .connectionType = (u8)map_to_connection_type[connection->type],
- .admin_state = connection->admin_state,
-#ifdef WITH_POLICY
- .priority = connection->priority,
- .tags = connection->tags,
-#endif /* WITH_POLICY */
- }
- };
- rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_create] Unexpected truncation of symbolic name string");
- //snprintf(msg.payload.interfaceName, INTERFACE_NAME_LEN, "%s", connection->interface_name);
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_CONNECTION,
- .size_in = sizeof(add_connection_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+ return s->hc_connection_create(s, connection);
}
-int
-hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
+int hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
+ hc_connection_t **connection_found)
{
- return _hc_connection_create(s, connection, false);
+ return s->hc_connection_get(s, connection, connection_found);
}
-int
-hc_connection_create_async(hc_sock_t * s, hc_connection_t * connection)
+int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
+ hc_connection_t *connection)
{
- return _hc_connection_create(s, connection, true);
+ return s->hc_connection_update_by_id(s, hc_connection_id, connection);
}
-/* CONNECTION GET */
-
-int
-hc_connection_get(hc_sock_t * s, hc_connection_t * connection,
- hc_connection_t ** connection_found)
+int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current,
+ hc_connection_t *connection_updated)
{
- hc_data_t * connections;
- hc_connection_t * found;
-
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[hc_connection_get] Unexpected truncation of connection string");
- DEBUG("[hc_connection_get] connection=%s", connection_s);
-
- if (hc_connection_list(s, &connections) < 0)
- return -1;
-
- /* Test */
- if (hc_connection_find(connections, connection, &found) < 0) {
- hc_data_free(connections);
- return -1;
- }
-
- if (found) {
- *connection_found = malloc(sizeof(hc_connection_t));
- if (!*connection_found)
- return -1;
- **connection_found = *found;
- } else {
- *connection_found = NULL;
- }
-
- hc_data_free(connections);
-
- return 0;
+ return s->hc_connection_update(s, connection_current, connection_updated);
}
-
-/* CONNECTION DELETE */
-
-int
-_hc_connection_delete(hc_sock_t * s, hc_connection_t * connection, bool async)
-{
- char connection_s[MAXSZ_HC_CONNECTION];
- int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
- if (rc >= MAXSZ_HC_CONNECTION)
- WARN("[_hc_connection_delete] Unexpected truncation of connection string");
- DEBUG("[_hc_connection_delete] connection=%s async=%s", connection_s, BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- remove_connection_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_CONNECTION,
- .length = 1,
- .seqNum = 0,
- },
- };
-
- if (connection->id) {
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- } else if (*connection->name) {
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", connection->name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- } else {
- hc_connection_t * connection_found;
- if (hc_connection_get(s, connection, &connection_found) < 0)
- return -1;
- if (!connection_found)
- return -1;
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection_found->id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
- free(connection_found);
- }
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_CONNECTION,
- .size_in = sizeof(remove_connection_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-int
-hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
+int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection)
{
- return _hc_connection_delete(s, connection, false);
+ return s->hc_connection_delete(s, connection);
}
-int
-hc_connection_delete_async(hc_sock_t * s, hc_connection_t * connection)
+int hc_connection_list(hc_sock_t *s, hc_data_t **pdata)
{
- return _hc_connection_delete(s, connection, true);
+ return s->hc_connection_list(s, pdata);
}
-/* CONNECTION LIST */
-
-int
-_hc_connection_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
-{
- DEBUG("[hc_connection_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_CONNECTIONS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_CONNECTIONS,
- .size_in = sizeof(list_connections_command),
- .size_out = sizeof(hc_connection_t),
- .parse = (HC_PARSE)hc_connection_parse,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state)
+{
+ return s->hc_connection_set_admin_state(s, conn_id_or_name, state);
}
-int
-hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
+#ifdef WITH_POLICY
+int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority)
{
- return _hc_connection_list(s, pdata, false);
+ return s->hc_connection_set_priority(s, conn_id_or_name, priority);
}
-int
-hc_connection_list_async(hc_sock_t * s, hc_data_t ** pdata)
+int hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags)
{
- return _hc_connection_list(s, pdata, true);
+ return s->hc_connection_set_tags(s, conn_id_or_name, tags);
}
+#endif // WITH_POLICY
+
+GENERATE_FIND(connection);
/* CONNECTION VALIDATE */
@@ -1597,8 +663,6 @@ hc_connection_parse(void * in, hc_connection_t * connection)
return 0;
}
-GENERATE_FIND(connection)
-
/* CONNECTION SNPRINTF */
/* /!\ Please update constants in header file upon changes */
@@ -1632,327 +696,169 @@ hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection
connection_type_str[connection->type]);
}
-/* CONNECTION SET ADMIN STATE */
-
-int
-_hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state, bool async)
+int hc_face_create(hc_sock_t *s, hc_face_t *face)
{
- int rc;
- DEBUG("[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s async=%s",
- conn_id_or_name, face_state_str[state], BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_admin_state_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_ADMIN_STATE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .admin_state = state,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_admin_state] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_ADMIN_STATE,
- .size_in = sizeof(connection_set_admin_state_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+ return s->hc_face_create(s, face);
}
-int
-hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state)
+int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found)
{
- return _hc_connection_set_admin_state(s, conn_id_or_name, state, false);
+ return s->hc_face_get(s, face, face_found);
}
-int
-hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state)
+int hc_face_delete(hc_sock_t *s, hc_face_t *face)
{
- return _hc_connection_set_admin_state(s, conn_id_or_name, state, true);
+ return s->hc_face_delete(s, face);
}
-int
-_hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority, bool async)
+int hc_face_list(hc_sock_t *s, hc_data_t **pdata)
{
- int rc;
- DEBUG("[hc_connection_set_priority] connection_id/name=%s priority=%d async=%s",
- conn_id_or_name, priority, BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_priority_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_PRIORITY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .priority = priority,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_priority] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_PRIORITY,
- .size_in = sizeof(connection_set_priority_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+ return s->hc_face_list(s, pdata);
}
-int
-hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
+int hc_face_list_async(hc_sock_t *s)
{
- return _hc_connection_set_priority(s, conn_id_or_name, priority, false);
+ return s->hc_face_list_async(s);
}
-int
-hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
+int hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state)
{
- return _hc_connection_set_priority(s, conn_id_or_name, priority, true);
+ return s->hc_face_set_admin_state(s, conn_id_or_name, state);
}
-int
-_hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags, bool async)
+#ifdef WITH_POLICY
+int hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority)
{
- int rc;
- DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s",
- conn_id_or_name, tags, BOOLSTR(async));
- struct {
- header_control_message hdr;
- connection_set_tags_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CONNECTION_SET_TAGS,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .tags = tags,
- },
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_connection_set_tags] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CONNECTION_SET_TAGS,
- .size_in = sizeof(connection_set_tags_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+ return s->hc_face_set_priority(s, conn_id_or_name, priority);
}
-int
-hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
+int hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags)
{
- return _hc_connection_set_tags(s, conn_id_or_name, tags, false);
+ return s->hc_face_set_tags(s, conn_id_or_name, tags);
}
+#endif /* WITH_POLICY */
+/* /!\ Please update constants in header file upon changes */
int
-hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
+hc_face_snprintf(char * s, size_t size, hc_face_t * face)
{
- return _hc_connection_set_tags(s, conn_id_or_name, tags, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Routes
- *----------------------------------------------------------------------------*/
+ /* URLs are also big enough to contain IP addresses in the hICN case */
+ char local[MAXSZ_URL];
+ char remote[MAXSZ_URL];
+#ifdef WITH_POLICY
+ char tags[MAXSZ_POLICY_TAGS];
+#endif /* WITH_POLICY */
+ int rc;
-/* ROUTE CREATE */
+ switch(face->face.type) {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_HICN_LISTENER:
+ rc = ip_address_snprintf(local, MAXSZ_URL,
+ &face->face.local_addr,
+ face->face.family);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0)
+ return rc;
+ rc = ip_address_snprintf(remote, MAXSZ_URL,
+ &face->face.remote_addr,
+ face->face.family);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0)
+ return rc;
+ break;
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ rc = url_snprintf(local, MAXSZ_URL, face->face.family,
+ &face->face.local_addr,
+ face->face.local_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0)
+ return rc;
+ rc = url_snprintf(remote, MAXSZ_URL, face->face.family,
+ &face->face.remote_addr,
+ face->face.remote_port);
+ if (rc >= MAXSZ_URL)
+ WARN("[hc_face_snprintf] Unexpected truncation of URL string");
+ if (rc < 0)
+ return rc;
+ break;
+ default:
+ return -1;
+ }
-int
-_hc_route_create(hc_sock_t * s, hc_route_t * route, bool async)
-{
- char route_s[MAXSZ_HC_ROUTE];
- int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
- if (rc >= MAXSZ_HC_ROUTE)
- WARN("[_hc_route_create] Unexpected truncation of route string");
+ // [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS)
+#ifdef WITH_POLICY
+ rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags);
+ if (rc >= MAXSZ_POLICY_TAGS)
+ WARN("[hc_face_snprintf] Unexpected truncation of policy tags string");
if (rc < 0)
- WARN("[_hc_route_create] Error building route string");
- else
- DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(route->family))
- return -1;
-
- struct {
- header_control_message hdr;
- add_route_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_ROUTE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = route->remote_addr,
- .cost = route->cost,
- .addressType = (u8)map_to_addr_type[route->family],
- .len = route->len,
- }
- };
-
- /*
- * The route commands expects the ID (or name that we don't use) as part of
- * the symbolicOrConnid attribute.
- */
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_route_create] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_ROUTE,
- .size_in = sizeof(add_route_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-int
-hc_route_create(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_create(s, route, false);
-}
+ return rc;
-int
-hc_route_create_async(hc_sock_t * s, hc_route_t * route)
-{
- return _hc_route_create(s, route, true);
+ return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)",
+ face->id,
+ face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
+ face_type_str[face->face.type],
+ local,
+ remote,
+ face_state_str[face->face.state],
+ face_state_str[face->face.admin_state],
+ face->face.priority,
+ tags);
+#else
+ return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s",
+ face->id,
+ face->name,
+ face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
+ face_type_str[face->face.type],
+ local,
+ remote,
+ face_state_str[face->face.state],
+ face_state_str[face->face.admin_state]);
+#endif /* WITH_POLICY */
}
-/* ROUTE DELETE */
-
int
-_hc_route_delete(hc_sock_t * s, hc_route_t * route, bool async)
+hc_connection_parse_to_face(void * in, hc_face_t * face)
{
- char route_s[MAXSZ_HC_ROUTE];
- int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
- if (rc >= MAXSZ_HC_ROUTE)
- WARN("[_hc_route_delete] Unexpected truncation of route string");
- DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async));
-
- if (!IS_VALID_FAMILY(route->family))
- return -1;
+ hc_connection_t connection;
- struct {
- header_control_message hdr;
- remove_route_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_ROUTE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = route->remote_addr,
- .addressType = (u8)map_to_addr_type[route->family],
- .len = route->len,
- }
- };
+ if (hc_connection_parse(in, &connection) < 0) {
+ ERROR("[hc_connection_parse_to_face] Could not parse connection");
+ return -1;
+ }
- /*
- * The route commands expects the ID (or name that we don't use) as part of
- * the symbolicOrConnid attribute.
- */
- snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_ROUTE,
- .size_in = sizeof(remove_route_command),
- .size_out = 0,
- .parse = NULL,
- };
+ if (hc_connection_to_face(&connection, face) < 0) {
+ ERROR("[hc_connection_parse_to_face] Could not convert connection to face.");
+ return -1;
+ }
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+ return 0;
}
-int
-hc_route_delete(hc_sock_t * s, hc_route_t * route)
+int hc_route_create(hc_sock_t * s, hc_route_t * route)
{
- return _hc_route_delete(s, route, false);
+ return s->hc_route_create(s, route);
}
-int
-hc_route_delete_async(hc_sock_t * s, hc_route_t * route)
+int hc_route_delete(hc_sock_t * s, hc_route_t * route)
{
- return _hc_route_delete(s, route, true);
-}
-
-/* ROUTE LIST */
-
-int
-_hc_route_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
-{
- //DEBUG("[hc_route_list] async=%s", BOOLSTR(async));
-
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_ROUTES,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_ROUTES,
- .size_in = sizeof(list_routes_command),
- .size_out = sizeof(hc_route_t),
- .parse = (HC_PARSE)hc_route_parse,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+ return s->hc_route_delete(s, route);
}
-int
-hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
+int hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
{
- return _hc_route_list(s, pdata, false);
+ return s->hc_route_list(s, pdata);
}
-int
-hc_route_list_async(hc_sock_t * s)
+int hc_route_list_async(hc_sock_t * s)
{
- return _hc_route_list(s, NULL, true);
+ return s->hc_route_list_async(s);
}
/* ROUTE PARSE */
@@ -2005,19 +911,6 @@ hc_route_snprintf(char * s, size_t size, hc_route_t * route)
MAXSZ_COST, route->cost, prefix, MAXSZ_LEN, route->len);
}
-/*----------------------------------------------------------------------------*
- * Face
- *
- * Face support is not directly available in hicn-light, but we can offer such
- * an interface through a combination of listeners and connections. The code
- * starts with some conversion functions between faces/listeners/connections.
- *
- * We also need to make sure that there always exist a (single) listener when a
- * connection is created, and in the hICN face case, that there is a single
- * connection attached to this listener.
- *
- *----------------------------------------------------------------------------*/
-
/* FACE -> LISTENER */
int
@@ -2236,484 +1129,25 @@ hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_
return 0;
}
-/* FACE CREATE */
-
-int
-hc_face_create(hc_sock_t * s, hc_face_t * face)
+int hc_punting_create(hc_sock_t *s, hc_punting_t *punting)
{
- hc_listener_t listener;
- hc_listener_t * listener_found;
-
- hc_connection_t connection;
- hc_connection_t * connection_found;
-
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_create] Unexpected truncation of face string");
- DEBUG("[hc_face_create] face=%s", face_s);
-
- switch(face->face.type)
- {
- case FACE_TYPE_HICN:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- if (hc_face_to_connection(face, &connection, true) < 0) {
- ERROR("[hc_face_create] Could not convert face to connection.");
- return -1;
- }
-
- /* Ensure we have a corresponding local listener */
- if (hc_connection_to_local_listener(&connection, &listener) < 0) {
- ERROR("[hc_face_create] Could not convert face to local listener.");
- return -1;
- }
-
- if (hc_listener_get(s, &listener, &listener_found) < 0) {
- ERROR("[hc_face_create] Could not retrieve listener");
- return -1;
- }
-
- if (!listener_found) {
- /* We need to create the listener if it does not exist */
- if (hc_listener_create(s, &listener) < 0) {
- ERROR("[hc_face_create] Could not create listener.");
- free(listener_found);
- return -1;
- }
- } else {
- free(listener_found);
- }
-
- /* Create corresponding connection */
- if (hc_connection_create(s, &connection) < 0) {
- ERROR("[hc_face_create] Could not create connection.");
- return -1;
- }
-
- /*
- * Once the connection is created, we need to list all connections
- * and compare with the current one to find the created face ID.
- */
- if (hc_connection_get(s, &connection, &connection_found) < 0) {
- ERROR("[hc_face_create] Could not retrieve connection");
- return -1;
- }
-
- if (!connection_found) {
- ERROR("[hc_face_create] Could not find newly created connection.");
- return -1;
- }
-
- face->id = connection_found->id;
- free(connection_found);
-
- break;
-
- case FACE_TYPE_HICN_LISTENER:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- if (hc_face_to_listener(face, &listener) < 0) {
- ERROR("Could not convert face to listener.");
- return -1;
- }
- if (hc_listener_create(s, &listener) < 0) {
- ERROR("[hc_face_create] Could not create listener.");
- return -1;
- }
- return -1;
- break;
- default:
- ERROR("[hc_face_create] Unknwon face type.");
-
- return -1;
- };
-
- return 0;
+ return s->hc_punting_create(s, punting);
}
-int
-hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found)
+int hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
+ hc_punting_t **punting_found)
{
- hc_listener_t listener;
- hc_listener_t * listener_found;
-
- hc_connection_t connection;
- hc_connection_t * connection_found;
-
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_get] Unexpected truncation of face string");
- DEBUG("[hc_face_get] face=%s", face_s);
-
- switch(face->face.type)
- {
- case FACE_TYPE_HICN:
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- if (hc_face_to_connection(face, &connection, false) < 0)
- return -1;
- if (hc_connection_get(s, &connection, &connection_found) < 0)
- return -1;
- if (!connection_found) {
- *face_found = NULL;
- return 0;
- }
- *face_found = malloc(sizeof(hc_face_t));
- hc_connection_to_face(connection_found, *face_found);
- free(connection_found);
- break;
-
- case FACE_TYPE_HICN_LISTENER:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- if (hc_face_to_listener(face, &listener) < 0)
- return -1;
- if (hc_listener_get(s, &listener, &listener_found) < 0)
- return -1;
- if (!listener_found) {
- *face_found = NULL;
- return 0;
- }
- *face_found = malloc(sizeof(hc_face_t));
- hc_listener_to_face(listener_found, *face_found);
- free(listener_found);
- break;
-
- default:
- return -1;
- }
-
- return 0;
-
-}
-
-/* FACE DELETE */
-
-int
-hc_face_delete(hc_sock_t * s, hc_face_t * face)
-{
- char face_s[MAXSZ_HC_FACE];
- int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
- if (rc >= MAXSZ_HC_FACE)
- WARN("[hc_face_delete] Unexpected truncation of face string");
- DEBUG("[hc_face_delete] face=%s", face_s);
-
- hc_connection_t connection;
- if (hc_face_to_connection(face, &connection, false) < 0) {
- ERROR("[hc_face_delete] Could not convert face to connection.");
- return -1;
- }
-
- if (hc_connection_delete(s, &connection) < 0) {
- ERROR("[hc_face_delete] Error removing connection");
- return -1;
- }
-
- /* If this is the last connection attached to the listener, remove it */
-
- hc_data_t * connections;
- hc_listener_t listener = {{0}};
-
- /*
- * Ensure we have a corresponding local listener
- * NOTE: hc_face_to_listener is not appropriate
- */
- if (hc_connection_to_local_listener(&connection, &listener) < 0) {
- ERROR("[hc_face_create] Could not convert face to local listener.");
- return -1;
- }
-#if 1
- /*
- * The name is generated to prepare listener creation, we need it to be
- * empty for deletion. The id should not need to be reset though.
- */
- listener.id = 0;
- memset(listener.name, 0, sizeof(listener.name));
-#endif
- if (hc_connection_list(s, &connections) < 0) {
- ERROR("[hc_face_delete] Error getting the list of listeners");
- return -1;
- }
-
- bool delete = true;
- foreach_connection(c, connections) {
- if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == 0) &&
- (c->local_port == listener.local_port) &&
- (strcmp(c->interface_name, listener.interface_name) == 0)) {
- delete = false;
- }
- }
-
- if (delete) {
- if (hc_listener_delete(s, &listener) < 0) {
- ERROR("[hc_face_delete] Error removing listener");
- return -1;
- }
- }
-
- hc_data_free(connections);
-
- return 0;
-
-
+ return s->hc_punting_get(s, punting, punting_found);
}
-/* FACE LIST */
-
-int
-hc_face_list(hc_sock_t * s, hc_data_t ** pdata)
+int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting)
{
- hc_data_t * connection_data;
- hc_face_t face;
-
- //DEBUG("[hc_face_list]");
-
- if (hc_connection_list(s, &connection_data) < 0) {
- ERROR("[hc_face_list] Could not list connections.");
- return -1;
- }
-
- hc_data_t * face_data = hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL);
- foreach_connection(c, connection_data) {
- if (hc_connection_to_face(c, &face) < 0) {
- ERROR("[hc_face_list] Could not convert connection to face.");
- goto ERR;
- }
- hc_data_push(face_data, &face);
- }
-
- *pdata = face_data;
- hc_data_free(connection_data);
- return 0;
-
-ERR:
- hc_data_free(connection_data);
- return -1;
+ return s->hc_punting_delete(s, punting);
}
-int
-hc_connection_parse_to_face(void * in, hc_face_t * face)
+int hc_punting_list(hc_sock_t *s, hc_data_t **pdata)
{
- hc_connection_t connection;
-
- if (hc_connection_parse(in, &connection) < 0) {
- ERROR("[hc_connection_parse_to_face] Could not parse connection");
- return -1;
- }
-
- if (hc_connection_to_face(&connection, face) < 0) {
- ERROR("[hc_connection_parse_to_face] Could not convert connection to face.");
- return -1;
- }
-
- return 0;
-}
-
-
-int
-hc_face_list_async(hc_sock_t * s)
-{
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_CONNECTIONS,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_CONNECTIONS,
- .size_in = sizeof(list_connections_command),
- .size_out = sizeof(hc_face_t),
- .parse = (HC_PARSE)hc_connection_parse_to_face,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, true);
-}
-
-/* /!\ Please update constants in header file upon changes */
-int
-hc_face_snprintf(char * s, size_t size, hc_face_t * face)
-{
- /* URLs are also big enough to contain IP addresses in the hICN case */
- char local[MAXSZ_URL];
- char remote[MAXSZ_URL];
-#ifdef WITH_POLICY
- char tags[MAXSZ_POLICY_TAGS];
-#endif /* WITH_POLICY */
- int rc;
-
- switch(face->face.type) {
- case FACE_TYPE_HICN:
- case FACE_TYPE_HICN_LISTENER:
- rc = ip_address_snprintf(local, MAXSZ_URL,
- &face->face.local_addr,
- face->face.family);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = ip_address_snprintf(remote, MAXSZ_URL,
- &face->face.remote_addr,
- face->face.family);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- break;
- case FACE_TYPE_TCP:
- case FACE_TYPE_UDP:
- case FACE_TYPE_TCP_LISTENER:
- case FACE_TYPE_UDP_LISTENER:
- rc = url_snprintf(local, MAXSZ_URL, face->face.family,
- &face->face.local_addr,
- face->face.local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- rc = url_snprintf(remote, MAXSZ_URL, face->face.family,
- &face->face.remote_addr,
- face->face.remote_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_face_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
- break;
- default:
- return -1;
- }
-
- // [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS)
-#ifdef WITH_POLICY
- rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags);
- if (rc >= MAXSZ_POLICY_TAGS)
- WARN("[hc_face_snprintf] Unexpected truncation of policy tags string");
- if (rc < 0)
- return rc;
-
- return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)",
- face->id,
- face->name,
- face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
- local,
- remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state],
- face->face.priority,
- tags);
-#else
- return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s",
- face->id,
- face->name,
- face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*",
- face_type_str[face->face.type],
- local,
- remote,
- face_state_str[face->face.state],
- face_state_str[face->face.admin_state]);
-#endif /* WITH_POLICY */
-}
-
-int
-hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t admin_state)
-{
- return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
-}
-
-int
-hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name,
- uint32_t priority)
-{
- return hc_connection_set_priority(s, conn_id_or_name, priority);
-}
-
-int
-hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name,
- policy_tags_t tags)
-{
- return hc_connection_set_tags(s, conn_id_or_name, tags);
-}
-
-/*----------------------------------------------------------------------------*
- * Punting
- *----------------------------------------------------------------------------*/
-
-int
-_hc_punting_create(hc_sock_t * s, hc_punting_t * punting, bool async)
-{
- int rc;
-
- if (hc_punting_validate(punting) < 0)
- return -1;
-
- struct {
- header_control_message hdr;
- add_punting_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_PUNTING,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = punting->prefix,
- .addressType = (u8)map_to_addr_type[punting->family],
- .len = punting->prefix_len,
- }
- };
- rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", punting->face_id);
- if (rc >= SYMBOLIC_NAME_LEN)
- WARN("[_hc_punting_create] Unexpected truncation of symbolic name string");
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_PUNTING,
- .size_in = sizeof(add_punting_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-int
-hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
-{
- return _hc_punting_create(s, punting, false);
-}
-
-int
-hc_punting_create_async(hc_sock_t * s, hc_punting_t * punting)
-{
- return _hc_punting_create(s, punting, true);
-}
-
-int hc_punting_get(hc_sock_t * s, hc_punting_t * punting, hc_punting_t ** punting_found)
-{
- ERROR("hc_punting_get not (yet) implemented.");
- return -1;
-}
-
-int hc_punting_delete(hc_sock_t * s, hc_punting_t * punting)
-{
- ERROR("hc_punting_delete not (yet) implemented.");
- return -1;
-}
-
-int hc_punting_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- ERROR("hc_punting_list not (yet) implemented.");
- return -1;
+ return s->hc_punting_list(s, pdata);
}
int hc_punting_validate(const hc_punting_t * punting)
@@ -2768,130 +1202,24 @@ int hc_punting_snprintf(char * s, size_t size, hc_punting_t * punting)
return -1;
}
-
-/*----------------------------------------------------------------------------*
- * Cache
- *----------------------------------------------------------------------------*/
-
-int
-_hc_cache_set_store(hc_sock_t * s, int enabled, bool async)
-{
- struct {
- header_control_message hdr;
- cache_store_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CACHE_STORE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .activate = enabled,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CACHE_STORE,
- .size_in = sizeof(cache_store_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-int
-hc_cache_set_store(hc_sock_t * s, int enabled)
+int hc_cache_set_store(hc_sock_t *s, int enabled)
{
- return _hc_cache_set_store(s, enabled, false);
+ return s->hc_cache_set_store(s, enabled);
}
-int
-hc_cache_set_store_async(hc_sock_t * s, int enabled)
+int hc_cache_set_serve(hc_sock_t *s, int enabled)
{
- return _hc_cache_set_store(s, enabled, true);
+ return s->hc_cache_set_serve(s, enabled);
}
-int
-_hc_cache_set_serve(hc_sock_t * s, int enabled, bool async)
-{
- struct {
- header_control_message hdr;
- cache_serve_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = CACHE_SERVE,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .activate = enabled,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_SET,
- .cmd_id = CACHE_SERVE,
- .size_in = sizeof(cache_serve_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-int
-hc_cache_set_serve(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_serve(s, enabled, false);
-}
-
-int
-hc_cache_set_serve_async(hc_sock_t * s, int enabled)
-{
- return _hc_cache_set_serve(s, enabled, true);
-}
-
-/*----------------------------------------------------------------------------*
- * Strategy
- *----------------------------------------------------------------------------*/
-
-// per prefix
-int
-hc_strategy_set(hc_sock_t * s /* XXX */)
+int hc_strategy_list(hc_sock_t *s, hc_data_t **data)
{
- return 0;
+ return s->hc_strategy_list(s, data);
}
-/* How to retrieve that from the forwarder ? */
-static const char * strategies[] = {
- "random",
- "load_balancer",
-};
-
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
-
-int
-hc_strategy_list(hc_sock_t * s, hc_data_t ** data)
+int hc_strategy_set(hc_sock_t *s /* XXX */)
{
- int rc;
-
- *data = hc_data_create(0, sizeof(hc_strategy_t), NULL);
-
- for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) {
- hc_strategy_t * strategy = (hc_strategy_t*)hc_data_get_next(*data);
- if (!strategy)
- return -1;
- rc = snprintf(strategy->name, MAXSZ_HC_STRATEGY, "%s", strategies[i]);
- if (rc >= MAXSZ_HC_STRATEGY)
- WARN("[hc_strategy_list] Unexpected truncation of strategy name string");
- (*data)->size++;
- }
-
- return 0;
+ return s->hc_strategy_set(s);
}
/* /!\ Please update constants in header file upon changes */
@@ -2901,187 +1229,33 @@ hc_strategy_snprintf(char * s, size_t size, hc_strategy_t * strategy)
return snprintf(s, size, "%s", strategy->name);
}
-/*----------------------------------------------------------------------------*
- * WLDR
- *----------------------------------------------------------------------------*/
-
-// per connection
-int
-hc_wldr_set(hc_sock_t * s /* XXX */)
+int hc_wldr_set(hc_sock_t *s /* XXX */)
{
- return 0;
+ return s->hc_wldr_set(s);
}
-/*----------------------------------------------------------------------------*
- * MAP-Me
- *----------------------------------------------------------------------------*/
-
-int
-hc_mapme_set(hc_sock_t * s, int enabled)
+int hc_mapme_set(hc_sock_t *s, int enabled)
{
- return 0;
+ return s->hc_mapme_set(s, enabled);
}
-int
-hc_mapme_set_discovery(hc_sock_t * s, int enabled)
+int hc_mapme_set_discovery(hc_sock_t *s, int enabled)
{
- return 0;
+ return s->hc_mapme_set_discovery(s, enabled);
}
-int
-hc_mapme_set_timescale(hc_sock_t * s, double timescale)
+int hc_mapme_set_timescale(hc_sock_t *s, double timescale)
{
- return 0;
+ return s->hc_mapme_set_timescale(s, timescale);
}
-int
-hc_mapme_set_retx(hc_sock_t * s, double timescale)
+int hc_mapme_set_retx(hc_sock_t *s, double timescale)
{
- return 0;
+ return s->hc_mapme_set_retx(s, timescale);
}
-/*----------------------------------------------------------------------------*
- * Policy
- *----------------------------------------------------------------------------*/
-
#ifdef WITH_POLICY
-/* POLICY CREATE */
-
-int
-_hc_policy_create(hc_sock_t * s, hc_policy_t * policy, bool async)
-{
- if (!IS_VALID_FAMILY(policy->family))
- return -1;
-
- struct {
- header_control_message hdr;
- add_policy_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = ADD_POLICY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
- .len = policy->len,
- .policy = policy->policy,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_CREATE,
- .cmd_id = ADD_POLICY,
- .size_in = sizeof(add_policy_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-int
-hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_create(s, policy, false);
-}
-
-int
-hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_create(s, policy, true);
-}
-
-/* POLICY DELETE */
-
-int
-_hc_policy_delete(hc_sock_t * s, hc_policy_t * policy, bool async)
-{
- if (!IS_VALID_FAMILY(policy->family))
- return -1;
-
- struct {
- header_control_message hdr;
- remove_policy_command payload;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = REMOVE_POLICY,
- .length = 1,
- .seqNum = 0,
- },
- .payload = {
- .address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
- .len = policy->len,
- }
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_DELETE,
- .cmd_id = REMOVE_POLICY,
- .size_in = sizeof(remove_policy_command),
- .size_out = 0,
- .parse = NULL,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
-}
-
-int
-hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_delete(s, policy, false);
-}
-
-int
-hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy)
-{
- return _hc_policy_delete(s, policy, true);
-}
-
-/* POLICY LIST */
-
-int
-_hc_policy_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
-{
- struct {
- header_control_message hdr;
- } msg = {
- .hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = LIST_POLICIES,
- .length = 0,
- .seqNum = 0,
- },
- };
-
- hc_command_params_t params = {
- .cmd = ACTION_LIST,
- .cmd_id = LIST_POLICIES,
- .size_in = sizeof(list_policies_command),
- .size_out = sizeof(hc_policy_t),
- .parse = (HC_PARSE)hc_policy_parse,
- };
-
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
-}
-
-int
-hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_policy_list(s, pdata, false);
-}
-
-int
-hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata)
-{
- return _hc_policy_list(s, pdata, true);
-}
-
/* POLICY PARSE */
int
@@ -3114,4 +1288,4 @@ hc_policy_snprintf(char * s, size_t size, hc_policy_t * policy)
return 0;
}
-#endif /* WITH_POLICY */
+#endif /* WITH_POLICY */ \ No newline at end of file
diff --git a/ctrl/libhicnctrl/src/api_private.h b/ctrl/libhicnctrl/src/api_private.h
new file mode 100644
index 000000000..3922e1f3c
--- /dev/null
+++ b/ctrl/libhicnctrl/src/api_private.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HICN_API_PRIVATE_H
+#define HICN_API_PRIVATE_H
+
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/commands.h>
+#include <hicn/util/token.h>
+#include <hicn/util/log.h>
+#include <hicn/util/map.h>
+
+#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0)
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
+
+#if 0
+#ifdef __APPLE__
+#define RANDBYTE() (u8)(arc4random() & 0xFF)
+#else
+#define RANDBYTE() (u8)(random() & 0xFF)
+#endif
+#endif
+#define RANDBYTE() (u8)(rand() & 0xFF)
+
+hc_connection_type_t
+connection_type_from_str(const char * str);
+
+extern const hc_connection_type_t map_from_list_connections_type[];
+extern const hc_connection_type_t map_from_encap_type[];
+extern const connection_type map_to_connection_type[];
+extern const listener_mode map_to_listener_mode[];
+extern const hc_connection_state_t map_from_list_connections_state[];
+extern const int map_from_addr_type[];
+extern const address_type map_to_addr_type[];
+extern const char * connection_state_str[];
+extern const char * connection_type_str[];
+
+typedef enum {
+ ENCAP_TCP,
+ ENCAP_UDP,
+ ENCAP_ETHER,
+ ENCAP_LOCAL,
+ ENCAP_HICN
+} EncapType;
+
+#define connection_state_to_face_state(x) ((face_state_t)(x))
+#define face_state_to_connection_state(x) ((hc_connection_state_t)(x))
+
+#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX))
+
+#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x)
+
+typedef struct hc_sock_impl_s hc_sock_impl_t;
+
+int hc_data_ensure_available(hc_data_t * data, size_t count);
+u8 *hc_data_get_next(hc_data_t * data);
+int hc_data_set_error(hc_data_t * data);
+
+int
+hc_connection_parse_to_face(void * in, hc_face_t * face);
+
+int
+hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face);
+
+int
+hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face);
+
+int
+hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener);
+
+int
+hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_t * listener);
+
+int
+hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool generate_name);
+
+struct hc_sock_s {
+ int (*hc_sock_get_next_seq)(hc_sock_t *s);
+ int (*hc_sock_set_nonblocking)(hc_sock_t *s);
+ int (*hc_sock_get_fd)(hc_sock_t *s);
+ int (*hc_sock_connect)(hc_sock_t *s);
+ int (*hc_sock_get_available)(hc_sock_t *s, u8 **buffer, size_t *size);
+ int (*hc_sock_send)(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq);
+ int (*hc_sock_recv)(hc_sock_t *s);
+ int (*hc_sock_process)(hc_sock_t *s, hc_data_t **data);
+ int (*hc_sock_callback)(hc_sock_t *s, hc_data_t **data);
+ int (*hc_sock_reset)(hc_sock_t *s);
+ void (*hc_sock_free)(hc_sock_t *s);
+
+ int (*hc_listener_create)(hc_sock_t *s, hc_listener_t *listener);
+ int (*hc_listener_create_async)(hc_sock_t *s, hc_listener_t *listener);
+ int (*hc_listener_get)(hc_sock_t *s, hc_listener_t *listener,
+ hc_listener_t **listener_found);
+ int (*hc_listener_delete)(hc_sock_t *s, hc_listener_t *listener);
+ int (*hc_listener_delete_async)(hc_sock_t *s, hc_listener_t *listener);
+ int (*hc_listener_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_listener_list_async)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_listener_validate)(const hc_listener_t *listener);
+ int (*hc_listener_cmp)(const hc_listener_t *l1, const hc_listener_t *l2);
+ int (*hc_listener_parse)(void *in, hc_listener_t *listener);
+
+ int (*hc_connection_create)(hc_sock_t *s, hc_connection_t *connection);
+ int (*hc_connection_create_async)(hc_sock_t *s, hc_connection_t *connection);
+ int (*hc_connection_get)(hc_sock_t *s, hc_connection_t *connection,
+ hc_connection_t **connection_found);
+ int (*hc_connection_update_by_id)(hc_sock_t *s, int hc_connection_id,
+ hc_connection_t *connection);
+ int (*hc_connection_update)(hc_sock_t *s, hc_connection_t *connection_current,
+ hc_connection_t *connection_updated);
+ int (*hc_connection_delete)(hc_sock_t *s, hc_connection_t *connection);
+ int (*hc_connection_delete_async)(hc_sock_t *s, hc_connection_t *connection);
+ int (*hc_connection_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_connection_list_async)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_connection_validate)(const hc_connection_t *connection);
+ int (*hc_connection_cmp)(const hc_connection_t *c1, const hc_connection_t *c2);
+ int (*hc_connection_parse)(void *in, hc_connection_t *connection);
+ int (*hc_connection_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+ int (*hc_connection_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+
+#ifdef WITH_POLICY
+ int (*hc_connection_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
+ int (*hc_connection_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
+ int (*hc_connection_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+ int (*hc_connection_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+#endif // WITH_POLICY
+
+ int (*hc_connection_snprintf)(char *s, size_t size,
+ const hc_connection_t *connection);
+
+ int (*hc_face_create)(hc_sock_t *s, hc_face_t *face);
+ int (*hc_face_get)(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found);
+ int (*hc_face_delete)(hc_sock_t *s, hc_face_t *face);
+ int (*hc_face_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_face_list_async)(hc_sock_t *s);
+ int (*hc_face_set_admin_state)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+ int (*hc_face_set_admin_state_async)(hc_sock_t * s, const char * conn_id_or_name, face_state_t state);
+
+#ifdef WITH_POLICY
+ int (*hc_face_set_priority)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
+ int (*hc_face_set_priority_async)(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority);
+ int (*hc_face_set_tags)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+ int (*hc_face_set_tags_async)(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags);
+#endif // WITH_POLICY
+
+ int (*hc_face_snprintf)(char *s, size_t size, hc_face_t *face);
+
+ int (*hc_route_parse)(void *in, hc_route_t *route);
+ int (*hc_route_create)(hc_sock_t * s, hc_route_t * route);
+ int (*hc_route_create_async)(hc_sock_t * s, hc_route_t * route);
+ int (*hc_route_delete)(hc_sock_t * s, hc_route_t * route);
+ int (*hc_route_delete_async)(hc_sock_t * s, hc_route_t * route);
+ int (*hc_route_list)(hc_sock_t * s, hc_data_t ** pdata);
+ int (*hc_route_list_async)(hc_sock_t * s);
+
+ int (*hc_punting_create)(hc_sock_t *s, hc_punting_t *punting);
+ int (*hc_punting_create_async)(hc_sock_t *s, hc_punting_t *punting);
+ int (*hc_punting_get)(hc_sock_t *s, hc_punting_t *punting,
+ hc_punting_t **punting_found);
+ int (*hc_punting_delete)(hc_sock_t *s, hc_punting_t *punting);
+ int (*hc_punting_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_punting_validate)(const hc_punting_t *punting);
+ int (*hc_punting_cmp)(const hc_punting_t *c1, const hc_punting_t *c2);
+ int (*hc_punting_parse)(void *in, hc_punting_t *punting);
+
+ int (*hc_cache_set_store)(hc_sock_t *s, int enabled);
+ int (*hc_cache_set_serve)(hc_sock_t *s, int enabled);
+ int (*hc_cache_set_store_async)(hc_sock_t *s, int enabled);
+ int (*hc_cache_set_serve_async)(hc_sock_t *s, int enabled);
+
+ int (*hc_strategy_list)(hc_sock_t *s, hc_data_t **data);
+ int (*hc_strategy_snprintf)(char *s, size_t size, hc_strategy_t *strategy);
+ int (*hc_strategy_set)(hc_sock_t *s /* XXX */);
+
+ int (*hc_wldr_set)(hc_sock_t *s /* XXX */);
+
+ int (*hc_mapme_set)(hc_sock_t *s, int enabled);
+ int (*hc_mapme_set_discovery)(hc_sock_t *s, int enabled);
+ int (*hc_mapme_set_timescale)(hc_sock_t *s, double timescale);
+ int (*hc_mapme_set_retx)(hc_sock_t *s, double timescale);
+
+#ifdef WITH_POLICY
+ int (*hc_policy_parse)(void *in, hc_policy_t *policy);
+ int (*hc_policy_create)(hc_sock_t *s, hc_policy_t *policy);
+ int (*hc_policy_create_async)(hc_sock_t *s, hc_policy_t *policy);
+ int (*hc_policy_delete)(hc_sock_t *s, hc_policy_t *policy);
+ int (*hc_policy_delete_async)(hc_sock_t *s, hc_policy_t *policy);
+ int (*hc_policy_list)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_policy_list_async)(hc_sock_t *s, hc_data_t **pdata);
+ int (*hc_policy_snprintf)(char *s, size_t size, hc_policy_t *policy);
+#endif // WITH_POLICY
+
+ // Reference to module containing the implementation
+ void *handle;
+};
+
+#endif // HICN_API_PRIVATE_H \ No newline at end of file
diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c
index fc81139d6..064eb77e3 100644
--- a/ctrl/libhicnctrl/src/cli.c
+++ b/ctrl/libhicnctrl/src/cli.c
@@ -48,6 +48,9 @@ foreach_object
#undef _
} hc_object_t;
+#define HICNLIGHT_PARAM "hicnlight"
+#define VPP_PARAM "vpp"
+
void
usage_header()
{
@@ -247,7 +250,7 @@ usage_connection(const char * prog, bool header, bool verbose)
void usage(const char * prog)
{
- fprintf(stderr, "Usage: %s [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog);
+ fprintf(stderr, "Usage: %s [ -z forwarder (hicnlight | vpp) ] [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog);
fprintf(stderr, "\n");
fprintf(stderr, "High-level commands\n");
fprintf(stderr, "\n");
@@ -319,15 +322,25 @@ foreach_face_type
int
-parse_options(int argc, char *argv[], hc_command_t * command)
+parse_options(int argc, char *argv[], hc_command_t * command, forwarder_t *forwarder)
{
command->object = OBJECT_UNDEFINED;
command->action = ACTION_CREATE;
int opt;
int family;
- while ((opt = getopt(argc, argv, "dflcrFLCRSh")) != -1) {
+ while ((opt = getopt(argc, argv, "dflcrFLCRShz:")) != -1) {
switch (opt) {
+ case 'z' :
+ if (strncmp(optarg, VPP_PARAM, strlen(VPP_PARAM)) == 0) {
+ *forwarder = VPP;
+ } else if (strncmp(optarg, HICNLIGHT_PARAM, strlen(HICNLIGHT_PARAM))) {
+ *forwarder = HICNLIGHT;
+ } else {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ break;
case 'd':
command->action = ACTION_DELETE;
break;
@@ -380,7 +393,7 @@ parse_options(int argc, char *argv[], hc_command_t * command)
switch(command->action) {
case ACTION_CREATE:
if ((argc - optind != 5) && (argc - optind != 6)) {
- usage_face_create(argv[0], true, false);
+ usage_face_create(argv[0], true, false);
goto ERR_PARAM;
}
/* NAME will be autogenerated (and currently not used) */
@@ -693,10 +706,12 @@ int main(int argc, char *argv[])
char buf_route[MAXSZ_HC_ROUTE];
char buf_strategy[MAXSZ_HC_STRATEGY];
- if (parse_options(argc, argv, &command) < 0)
+ forwarder_t forwarder = HICNLIGHT;
+
+ if (parse_options(argc, argv, &command, &forwarder) < 0)
die(OPTIONS, "Bad arguments");
- hc_sock_t * s = hc_sock_create();
+ hc_sock_t * s = hc_sock_create_forwarder(forwarder);
if (!s)
die(SOCKET, "Error creating socket.");
diff --git a/ctrl/libhicnctrl/src/modules/CMakeLists.txt b/ctrl/libhicnctrl/src/modules/CMakeLists.txt
new file mode 100644
index 000000000..e07ab8c99
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/CMakeLists.txt
@@ -0,0 +1,48 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+
+list(APPEND HICNLIGHT_MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_api.c
+)
+
+build_module(hicnlightctrl_module
+ SHARED
+ SOURCES ${HICNLIGHT_MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILE_FLAGS}
+)
+
+if(BUILD_HICNPLUGIN AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ list(APPEND HICNLIGHT_PLUGIN_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin_api.c
+ )
+
+ build_module(vppctrl_module
+ SHARED
+ SOURCES ${HICNLIGHT_PLUGIN_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ LINK_LIBRARIES ${HICNPLUGIN_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
+ COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES}
+ INCLUDE_DIRS ${INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILE_FLAGS}
+ LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs"
+ )
+
+endif() \ No newline at end of file
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_api.c
new file mode 100644
index 000000000..d1a055777
--- /dev/null
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_api.c
@@ -0,0 +1,2278 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file api.c
+ * \brief Implementation of hICN control library API
+ */
+
+#include "api_private.h"
+
+#include <assert.h> // assert
+#include <stdbool.h>
+#include <stdio.h> // snprintf
+#include <string.h> // memmove, strcasecmp
+#include <sys/socket.h> // socket
+#include <unistd.h> // close, fcntl
+#include <fcntl.h> // fcntl
+#include <sys/types.h> // getpid
+#include <unistd.h> // getpid
+#ifdef __linux__
+#include <sys/syscall.h>
+#define gettid() syscall(SYS_gettid)
+#endif /* __linux__ */
+#include <strings.h>
+
+#define PORT 9695
+
+#define BOOLSTR(x) ((x) ? "true" : "false")
+
+/*
+ * Internal state associated to a pending request
+ */
+typedef struct {
+ int seq;
+ hc_data_t * data;
+ /* Information used to process results */
+ int size_in;
+ int (*parse)(const u8 * src, u8 * dst);
+} hc_sock_request_t;
+
+/**
+ * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
+ * the header_control_message structure. The forwarder simply answers back the
+ * original sequence number. We maintain a map of such sequence number to
+ * outgoing queries so that replied can be demultiplexed and treated
+ * appropriately.
+ */
+TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
+TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, generic_snprintf);
+
+struct hc_sock_light_s {
+ /* This must be the first element of the struct */
+ hc_sock_t vft;
+
+ char * url;
+ int fd;
+
+ /* Partial receive buffer */
+ u8 buf[RECV_BUFLEN];
+ size_t roff; /**< Read offset */
+ size_t woff; /**< Write offset */
+
+ /*
+ * Because received messages are potentially unbounded in size, we might not
+ * guarantee that we can store a full packet before processing it. We must
+ * implement a very simple state machine remembering the current parsing
+ * status in order to partially process the packet.
+ */
+ size_t remaining;
+ u32 send_id;
+
+ /* Next sequence number to be used for requests */
+ int seq;
+
+ /* Request being parsed (NULL if none) */
+ hc_sock_request_t * cur_request;
+
+ bool async;
+ hc_sock_map_t * map;
+};
+
+typedef struct hc_sock_light_s hc_sock_light_t;
+
+#define TO_HC_SOCK_LIGHT(s) (hc_sock_light_t*)(s)
+
+hc_sock_request_t *
+hc_sock_request_create(int seq, hc_data_t * data, HC_PARSE parse)
+{
+ assert(data);
+
+ hc_sock_request_t * request = malloc(sizeof(hc_sock_request_t));
+ if (!request)
+ return NULL;
+ request->seq = seq;
+ request->data = data;
+ request->parse = parse;
+ return request;
+}
+
+void
+hc_sock_light_request_free(hc_sock_request_t * request)
+{
+ free(request);
+}
+
+/*
+ * list was working with all seq set to 0, but it seems hicnLightControl uses
+ * 1, and replies with the same seqno
+ */
+#define HICN_CTRL_SEND_SEQ_INIT 1
+#define HICN_CTRL_RECV_SEQ_INIT 1
+
+#define MAX(x, y) ((x > y) ? x : y)
+
+/**
+ * In practise, we want to preserve enough room to store a full packet of
+ * average expected size (say a header + N payload elements).
+ */
+#define AVG_ELEMENTS (1 << DEFAULT_SIZE_LOG)
+#define AVG_BUFLEN (sizeof(hc_msg_header_t) + AVG_ELEMENTS * sizeof(hc_msg_payload_t))
+
+/*
+ * We should at least have buffer space allowing to store one processable unit
+ * of data, either the header of the maximum possible payload
+ */
+#define MIN_BUFLEN MAX(sizeof(hc_msg_header_t), sizeof(hc_msg_payload_t))
+
+static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
+
+/******************************************************************************
+ * Message helper types and aliases
+ ******************************************************************************/
+
+#define foreach_hc_command \
+ _(add_connection) \
+ _(remove_connection) \
+ _(list_connections) \
+ _(add_listener) \
+ _(remove_listener) \
+ _(list_listeners) \
+ _(add_route) \
+ _(remove_route) \
+ _(list_routes) \
+ _(cache_store) \
+ _(cache_serve) \
+ /*_(cache_clear) */ \
+ _(set_strategy) \
+ _(set_wldr) \
+ _(add_punting) \
+ _(mapme_activator) \
+ _(mapme_timing)
+
+typedef header_control_message hc_msg_header_t;
+
+typedef union {
+#define _(x) x ## _command x;
+ foreach_hc_command
+#undef _
+} hc_msg_payload_t;
+
+
+typedef struct hc_msg_s {
+ hc_msg_header_t hdr;
+ hc_msg_payload_t payload;
+} hc_msg_t;
+
+/******************************************************************************
+ * Control socket
+ ******************************************************************************/
+
+/**
+ * \brief Parse a connection URL into a sockaddr
+ * \param [in] url - URL
+ * \param [out] sa - Resulting struct sockaddr, expected zero'ed.
+ * \return 0 if parsing succeeded, a negative error value otherwise.
+ */
+static int
+_hc_sock_light_parse_url(const char * url, struct sockaddr * sa)
+{
+ /* FIXME URL parsing is currently not implemented */
+ assert(!url);
+
+#ifdef __linux__
+ srand(time(NULL) ^ getpid() ^ gettid());
+#else
+ srand((unsigned int )(time(NULL) ^ getpid()));
+#endif /* __linux__ */
+
+ /*
+ * A temporary solution is to inspect the sa_family fields of the passed in
+ * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP
+ * connection to localhost.
+ */
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ case AF_INET:
+ {
+ struct sockaddr_in * sai = (struct sockaddr_in *)sa;
+ sai->sin_family = AF_INET;
+ sai->sin_port = htons(PORT);
+ sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 * sai6 = (struct sockaddr_in6 *)sa;
+ sai6->sin6_family = AF_INET6;
+ sai6->sin6_port = htons(PORT);
+ sai6->sin6_addr = loopback_addr;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+_hc_sock_light_reset(hc_sock_t * socket)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ s->roff = s->woff = 0;
+ s->remaining = 0;
+ return 0;
+}
+
+void
+_hc_sock_light_free(hc_sock_t * socket)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ hc_sock_request_t ** request_array = NULL;
+ int n = hc_sock_map_get_value_array(s->map, &request_array);
+ if (n < 0) {
+ ERROR("Could not retrieve pending request array for freeing up resources");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hc_sock_request_t * request = request_array[i];
+ if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
+ ERROR("[hc_sock_light_process] Error removing request from map");
+ hc_sock_light_request_free(request);
+ }
+ free(request_array);
+ }
+
+ hc_sock_map_free(s->map);
+ if (s->url)
+ free(s->url);
+ close(s->fd);
+ free(s);
+}
+
+static int
+_hc_sock_light_get_next_seq(hc_sock_t * socket)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return s->seq++;
+}
+
+static int
+_hc_sock_light_set_nonblocking(hc_sock_t * socket)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0);
+}
+
+static int
+_hc_sock_light_get_fd(hc_sock_t * socket)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ return s->fd;
+}
+
+static int
+_hc_sock_light_connect(hc_sock_t * socket)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ struct sockaddr_storage ss;
+ memset(&ss, 0, sizeof(struct sockaddr_storage));
+
+ if (_hc_sock_light_parse_url(s->url, (struct sockaddr *)&ss) < 0)
+ goto ERR_PARSE;
+
+ size_t size = ss.ss_family == AF_INET
+ ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6);
+ if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) //sizeof(struct sockaddr)) < 0)
+ goto ERR_CONNECT;
+
+ return 0;
+
+ERR_CONNECT:
+ERR_PARSE:
+ return -1;
+}
+
+static int
+_hc_sock_light_send(hc_sock_t * socket, hc_msg_t * msg, size_t msglen, int seq)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc;
+ msg->hdr.seqNum = seq;
+ rc = (int)send(s->fd, msg, msglen, 0);
+ if (rc < 0) {
+ perror("hc_sock_light_send");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_hc_sock_light_get_available(hc_sock_t * socket, u8 ** buffer, size_t * size)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ *buffer = s->buf + s->woff;
+ *size = RECV_BUFLEN - s->woff;
+
+ return 0;
+}
+
+static int
+_hc_sock_light_recv(hc_sock_t * socket)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int rc;
+
+ /*
+ * This condition should be ensured to guarantee correct processing of
+ * messages
+ */
+ assert(RECV_BUFLEN - s->woff > MIN_BUFLEN);
+
+ rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0);
+ if (rc == 0) {
+ /* Connection has been closed */
+ return 0;
+ }
+ if (rc < 0) {
+ /*
+ * Let's not return 0 which currently means the socket has been closed
+ */
+ if (errno == EWOULDBLOCK)
+ return -1;
+ perror("hc_sock_light_recv");
+ return -1;
+ }
+ s->woff += rc;
+ return rc;
+}
+
+/*
+ * Returns -99 in case of internal error, -1 in case of API command failure
+ */
+static int
+_hc_sock_light_process(hc_sock_t * socket, hc_data_t ** data)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int err = 0;
+
+ /* We must have received at least one byte */
+ size_t available = s->woff - s->roff;
+
+ while(available > 0) {
+
+ if (!s->cur_request) { // No message being parsed, alternatively (remaining == 0)
+ hc_msg_t * msg = (hc_msg_t*)(s->buf + s->roff);
+
+ /* We expect a message header */
+ if (available < sizeof(hc_msg_header_t)) {
+ break;
+ }
+
+ hc_sock_request_t * request = NULL;
+ if (hc_sock_map_get(s->map, msg->hdr.seqNum, &request) < 0) {
+ ERROR("[hc_sock_light_process] Error searching for matching request");
+ return -99;
+ }
+ if (!request) {
+ ERROR("[hc_sock_light_process] No request matching received sequence number");
+ return -99;
+ }
+
+ s->remaining = msg->hdr.length;
+ switch(msg->hdr.messageType) {
+ case ACK_LIGHT:
+ assert(s->remaining == 1);
+ assert(!data);
+ s->cur_request = request;
+ break;
+ case NACK_LIGHT:
+ assert(s->remaining == 1);
+ assert(!data);
+ hc_data_set_error(request->data);
+ s->cur_request = request;
+ err = -1;
+ break;
+ case RESPONSE_LIGHT:
+ assert(data);
+ if (s->remaining == 0) {
+ hc_data_set_complete(request->data);
+ *data = request->data;
+ if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
+ ERROR("[hc_sock_light_process] Error removing request from map");
+ hc_sock_light_request_free(request);
+ } else {
+ /* We only remember it if there is still data to parse */
+ s->cur_request = request;
+ }
+ break;
+ default:
+ ERROR("[hc_sock_light_process] Invalid response received");
+ return -99;
+ }
+
+ available -= sizeof(hc_msg_header_t);
+ s->roff += sizeof(hc_msg_header_t);
+ } else {
+ /* We expect the complete payload, or at least a chunk of it */
+ size_t num_chunks = available / s->cur_request->data->in_element_size;
+ if (num_chunks == 0)
+ break;
+ if (num_chunks > s->remaining)
+ num_chunks = s->remaining;
+
+ if (!s->cur_request->parse) {
+ /* If we don't need to parse results, then we can directly push
+ * all of them into the result data structure */
+ hc_data_push_many(s->cur_request->data, s->buf + s->roff, num_chunks);
+ } else {
+ int rc;
+ rc = hc_data_ensure_available(s->cur_request->data, num_chunks);
+ if (rc < 0) {
+ ERROR("[hc_sock_light_process] Error in hc_data_ensure_available");
+ return -99;
+ }
+ for (int i = 0; i < num_chunks; i++) {
+ u8 * dst = hc_data_get_next(s->cur_request->data);
+ if (!dst) {
+ ERROR("[hc_sock_light_process] Error in hc_data_get_next");
+ return -99;
+ }
+
+ rc = s->cur_request->parse(s->buf + s->roff + i * s->cur_request->data->in_element_size, dst);
+ if (rc < 0) {
+ ERROR("[hc_sock_light_process] Error in parse");
+ err = -99; /* FIXME we let the loop complete (?) */
+ }
+ s->cur_request->data->size++;
+ }
+ }
+
+ s->remaining -= num_chunks;
+ available -= num_chunks * s->cur_request->data->in_element_size;
+ s->roff += num_chunks * s->cur_request->data->in_element_size;
+ if (s->remaining == 0) {
+ if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
+ ERROR("[hc_sock_light_process] Error removing request from map");
+ return -99;
+ }
+ hc_data_set_complete(s->cur_request->data);
+ if (data)
+ *data = s->cur_request->data;
+ hc_sock_light_request_free(s->cur_request);
+ s->cur_request = NULL;
+ }
+
+ }
+ }
+
+ /* Make sure there is enough remaining space in the buffer */
+ if (RECV_BUFLEN - s->woff < AVG_BUFLEN) {
+ /*
+ * There should be no overlap provided a sufficiently large BUFLEN, but
+ * who knows.
+ */
+ memmove(s->buf, s->buf + s->roff, s->woff - s->roff);
+ s->woff -= s->roff;
+ s->roff = 0;
+ }
+
+ return err;
+}
+
+static int
+_hc_sock_light_callback(hc_sock_t * socket, hc_data_t ** pdata)
+{
+ hc_data_t * data;
+
+ for (;;) {
+ int n = _hc_sock_light_recv(socket);
+ if (n == 0)
+ goto ERR_EOF;
+ if (n < 0) {
+ switch(errno) {
+ case ECONNRESET:
+ case ENODEV:
+ /* Forwarder restarted */
+ WARN("Forwarder likely restarted: not (yet) implemented");
+ goto ERR;
+ case EWOULDBLOCK:
+ //DEBUG("Would block... stop reading from socket");
+ goto END;
+ default:
+ perror("hc_sock_light_recv");
+ goto ERR;
+ }
+ }
+ if (_hc_sock_light_process(socket, &data) < 0) {
+ goto ERR;
+ }
+ }
+END:
+ if (pdata)
+ *pdata = data;
+ else
+ hc_data_free(data);
+ return 0;
+
+ERR:
+ hc_data_free(data);
+ERR_EOF:
+ return -1;
+}
+
+/******************************************************************************
+ * Command-specific structures and functions
+ ******************************************************************************/
+
+typedef int (*HC_PARSE)(const u8 *, u8 *);
+
+typedef struct {
+ hc_action_t cmd;
+ command_id cmd_id;
+ size_t size_in;
+ size_t size_out;
+ HC_PARSE parse;
+} hc_command_params_t;
+
+static int
+_hc_execute_command(hc_sock_t * socket, hc_msg_t * msg, size_t msg_len,
+ hc_command_params_t * params, hc_data_t ** pdata, bool async)
+{
+ hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
+ int ret;
+ if (async)
+ assert(!pdata);
+
+ /* Sanity check */
+ switch(params->cmd) {
+ case ACTION_CREATE:
+ assert(params->size_in != 0); /* payload repeated */
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_DELETE:
+ assert(params->size_in != 0); /* payload repeated */
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ case ACTION_LIST:
+ assert(params->size_in != 0);
+ assert(params->size_out != 0);
+ assert(params->parse != NULL);
+ break;
+ case ACTION_SET:
+ assert(params->size_in != 0);
+ assert(params->size_out == 0);
+ assert(params->parse == NULL);
+ break;
+ default:
+ return -1;
+ }
+
+ //hc_sock_light_reset(s);
+
+ /* XXX data will at least store the result (complete) */
+ hc_data_t * data = hc_data_create(params->size_in, params->size_out, NULL);
+ if (!data) {
+ ERROR("[_hc_execute_command] Could not create data storage");
+ goto ERR_DATA;
+ }
+
+ int seq = _hc_sock_light_get_next_seq(socket);
+
+ /* Create state used to process the request */
+ hc_sock_request_t * request = NULL;
+ request = hc_sock_request_create(seq, data, params->parse);
+ if (!request) {
+ ERROR("[_hc_execute_command] Could not create request state");
+ goto ERR_REQUEST;
+ }
+
+ /* Add state to map */
+ if (hc_sock_map_add(s->map, seq, request) < 0) {
+ ERROR("[_hc_execute_command] Error adding request state to map");
+ goto ERR_MAP;
+ }
+
+ if (_hc_sock_light_send(socket, msg, msg_len, seq) < 0) {
+ ERROR("[_hc_execute_command] Error sending message");
+ goto ERR_PROCESS;
+ }
+
+ if (async)
+ return 0;
+
+ while(!data->complete) {
+ /*
+ * As the socket is non blocking it might happen that we need to read
+ * several times before success... shall we alternate between blocking
+ * and non-blocking mode ?
+ */
+ int n = _hc_sock_light_recv(socket);
+ if (n == 0)
+ goto ERR_EOF;
+ if (n < 0)
+ continue; //break;
+ int rc = _hc_sock_light_process(socket, pdata);
+ switch(rc) {
+ case 0:
+ break;
+ case -1:
+ ret = rc;
+ break;
+ case -99:
+ ERROR("[_hc_execute_command] Error processing socket results");
+ goto ERR;
+ break;
+ default:
+ ERROR("[_hc_execute_command] Unexpected return value");
+ goto ERR;
+ }
+ }
+
+ERR_EOF:
+ ret = data->ret;
+ if (!data->complete)
+ return -1;
+ if (!pdata)
+ hc_data_free(data);
+
+ return ret;
+
+ERR_PROCESS:
+ERR_MAP:
+ hc_sock_light_request_free(request);
+ERR:
+ERR_REQUEST:
+ hc_data_free(data);
+ERR_DATA:
+ return -99;
+}
+
+/*----------------------------------------------------------------------------*
+ * Listeners
+ *----------------------------------------------------------------------------*/
+
+/* LISTENER CREATE */
+
+static int
+_hc_listener_create_internal(hc_sock_t * socket, hc_listener_t * listener, bool async)
+{
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[_hc_listener_create] Unexpected truncation of listener string");
+ DEBUG("[_hc_listener_create] listener=%s async=%s", listener_s,
+ BOOLSTR(async));
+
+ if (!IS_VALID_FAMILY(listener->family))
+ return -1;
+
+ if (!IS_VALID_CONNECTION_TYPE(listener->type))
+ return -1;
+
+ struct {
+ header_control_message hdr;
+ add_listener_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = ADD_LISTENER,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .address = listener->local_addr,
+ .port = htons(listener->local_port),
+ .addressType = (u8)map_to_addr_type[listener->family],
+ .listenerMode = (u8)map_to_listener_mode[listener->type],
+ .connectionType = (u8)map_to_connection_type[listener->type],
+ }
+ };
+
+ rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_listener_create] Unexpected truncation of symbolic name string");
+
+ rc = snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name);
+ if (rc >= INTERFACE_LEN)
+ WARN("[_hc_listener_create] Unexpected truncation of interface name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = ADD_LISTENER,
+ .size_in = sizeof(add_listener_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_create_internal(s, listener, false);
+}
+
+static int
+_hc_listener_create_async(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_create_internal(s, listener, true);
+}
+
+/* LISTENER LIST */
+
+static int
+_hc_listener_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
+{
+ DEBUG("[hc_listener_list] async=%s", BOOLSTR(async));
+
+ struct {
+ header_control_message hdr;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = LIST_LISTENERS,
+ .length = 0,
+ .seqNum = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = LIST_LISTENERS,
+ .size_in = sizeof(list_listeners_command),
+ .size_out = sizeof(hc_listener_t),
+ .parse = (HC_PARSE)hc_listener_parse,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+static int
+_hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_listener_list_internal(s, pdata, false);
+}
+
+static int
+_hc_listener_list_async(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_listener_list_internal(s, pdata, true);
+}
+
+/* LISTENER GET */
+
+static int
+_hc_listener_get(hc_sock_t * socket, hc_listener_t * listener,
+ hc_listener_t ** listener_found)
+{
+ hc_data_t * listeners;
+ hc_listener_t * found;
+
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[hc_listener_get] Unexpected truncation of listener string");
+ DEBUG("[hc_listener_get] listener=%s", listener_s);
+
+ if (_hc_listener_list(socket, &listeners) < 0)
+ return -1;
+
+ /* Test */
+ if (hc_listener_find(listeners, listener, &found) < 0) {
+ hc_data_free(listeners);
+ return -1;
+ }
+
+ if (found) {
+ *listener_found = malloc(sizeof(hc_listener_t));
+ if (!*listener_found)
+ return -1;
+ **listener_found = *found;
+ } else {
+ *listener_found = NULL;
+ }
+
+ hc_data_free(listeners);
+
+ return 0;
+}
+
+
+/* LISTENER DELETE */
+
+static int
+_hc_listener_delete_internal(hc_sock_t * socket, hc_listener_t * listener, bool async)
+{
+ char listener_s[MAXSZ_HC_LISTENER];
+ int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener);
+ if (rc >= MAXSZ_HC_LISTENER)
+ WARN("[_hc_listener_delete] Unexpected truncation of listener string");
+ DEBUG("[_hc_listener_delete] listener=%s async=%s", listener_s,
+ BOOLSTR(async));
+
+ struct {
+ header_control_message hdr;
+ remove_listener_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = REMOVE_LISTENER,
+ .length = 1,
+ .seqNum = 0,
+ },
+ };
+
+ if (listener->id) {
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
+ } else if (*listener->name) {
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listener->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
+ } else {
+ hc_listener_t * listener_found;
+ if (_hc_listener_get(socket, listener, &listener_found) < 0)
+ return -1;
+ if (!listener_found)
+ return -1;
+ rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener_found->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_listener_delete] Unexpected truncation of symbolic name string");
+ free(listener_found);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = REMOVE_LISTENER,
+ .size_in = sizeof(remove_listener_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_delete_internal(s, listener, false);
+}
+
+static int
+_hc_listener_delete_async(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_delete_internal(s, listener, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * CONNECTION
+ *----------------------------------------------------------------------------*/
+
+/* CONNECTION CREATE */
+
+static int
+_hc_connection_create_internal(hc_sock_t * socket, hc_connection_t * connection, bool async)
+{
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN("[_hc_connection_create] Unexpected truncation of connection string");
+ DEBUG("[_hc_connection_create] connection=%s async=%s", connection_s, BOOLSTR(async));
+
+ if (hc_connection_validate(connection) < 0)
+ return -1;
+
+ struct {
+ header_control_message hdr;
+ add_connection_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = ADD_CONNECTION,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .remoteIp = connection->remote_addr,
+ .localIp = connection->local_addr,
+ .remotePort = htons(connection->remote_port),
+ .localPort = htons(connection->local_port),
+ .ipType = (u8)map_to_addr_type[connection->family],
+ .connectionType = (u8)map_to_connection_type[connection->type],
+ .admin_state = connection->admin_state,
+#ifdef WITH_POLICY
+ .priority = connection->priority,
+ .tags = connection->tags,
+#endif /* WITH_POLICY */
+ }
+ };
+ rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_create] Unexpected truncation of symbolic name string");
+ //snprintf(msg.payload.interfaceName, INTERFACE_NAME_LEN, "%s", connection->interface_name);
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = ADD_CONNECTION,
+ .size_in = sizeof(add_connection_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_create_internal(s, connection, false);
+}
+
+static int
+_hc_connection_create_async(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_create_internal(s, connection, true);
+}
+
+/* CONNECTION LIST */
+
+static int
+_hc_connection_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
+{
+ DEBUG("[hc_connection_list] async=%s", BOOLSTR(async));
+
+ struct {
+ header_control_message hdr;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = LIST_CONNECTIONS,
+ .length = 0,
+ .seqNum = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = LIST_CONNECTIONS,
+ .size_in = sizeof(list_connections_command),
+ .size_out = sizeof(hc_connection_t),
+ .parse = (HC_PARSE)hc_connection_parse,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+static int
+_hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_connection_list_internal(s, pdata, false);
+}
+
+static int
+_hc_connection_list_async(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_connection_list_internal(s, pdata, true);
+}
+
+/* CONNECTION GET */
+
+static int
+_hc_connection_get(hc_sock_t * socket, hc_connection_t * connection,
+ hc_connection_t ** connection_found)
+{
+ hc_data_t * connections;
+ hc_connection_t * found;
+
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN("[hc_connection_get] Unexpected truncation of connection string");
+ DEBUG("[hc_connection_get] connection=%s", connection_s);
+
+ if (_hc_connection_list(socket, &connections) < 0)
+ return -1;
+
+ /* Test */
+ if (hc_connection_find(connections, connection, &found) < 0) {
+ hc_data_free(connections);
+ return -1;
+ }
+
+ if (found) {
+ *connection_found = malloc(sizeof(hc_connection_t));
+ if (!*connection_found)
+ return -1;
+ **connection_found = *found;
+ } else {
+ *connection_found = NULL;
+ }
+
+ hc_data_free(connections);
+
+ return 0;
+}
+
+
+/* CONNECTION DELETE */
+
+static int
+_hc_connection_delete_internal(hc_sock_t * socket, hc_connection_t * connection, bool async)
+{
+ char connection_s[MAXSZ_HC_CONNECTION];
+ int rc = hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection);
+ if (rc >= MAXSZ_HC_CONNECTION)
+ WARN("[_hc_connection_delete] Unexpected truncation of connection string");
+ DEBUG("[_hc_connection_delete] connection=%s async=%s", connection_s, BOOLSTR(async));
+
+ struct {
+ header_control_message hdr;
+ remove_connection_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = REMOVE_CONNECTION,
+ .length = 1,
+ .seqNum = 0,
+ },
+ };
+
+ if (connection->id) {
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
+ } else if (*connection->name) {
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", connection->name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
+ } else {
+ hc_connection_t * connection_found;
+ if (_hc_connection_get(socket, connection, &connection_found) < 0)
+ return -1;
+ if (!connection_found)
+ return -1;
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection_found->id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_delete] Unexpected truncation of symbolic name string");
+ free(connection_found);
+ }
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = REMOVE_CONNECTION,
+ .size_in = sizeof(remove_connection_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_delete_internal(s, connection, false);
+}
+
+static int
+_hc_connection_delete_async(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_delete_internal(s, connection, true);
+}
+
+static int
+_hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id,
+ hc_connection_t *connection)
+{
+ // Not implemented
+ return -1;
+}
+
+static int
+_hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current,
+ hc_connection_t *connection_updated)
+{
+ // Not implemented
+ return -1;
+}
+
+/* CONNECTION SET ADMIN STATE */
+
+static int
+_hc_connection_set_admin_state_internal(hc_sock_t * socket, const char * conn_id_or_name,
+ face_state_t state, bool async)
+{
+ int rc;
+ DEBUG("[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s async=%s",
+ conn_id_or_name, face_state_str[state], BOOLSTR(async));
+ struct {
+ header_control_message hdr;
+ connection_set_admin_state_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = CONNECTION_SET_ADMIN_STATE,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .admin_state = state,
+ },
+ };
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_set_admin_state] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = CONNECTION_SET_ADMIN_STATE,
+ .size_in = sizeof(connection_set_admin_state_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
+ face_state_t state)
+{
+ return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, false);
+}
+
+static int
+_hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name,
+ face_state_t state)
+{
+ return _hc_connection_set_admin_state_internal(s, conn_id_or_name, state, true);
+}
+
+#ifdef WITH_POLICY
+
+static int
+_hc_connection_set_priority_internal(hc_sock_t * socket, const char * conn_id_or_name,
+ uint32_t priority, bool async)
+{
+ int rc;
+ DEBUG("[hc_connection_set_priority] connection_id/name=%s priority=%d async=%s",
+ conn_id_or_name, priority, BOOLSTR(async));
+ struct {
+ header_control_message hdr;
+ connection_set_priority_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = CONNECTION_SET_PRIORITY,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .priority = priority,
+ },
+ };
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_set_priority] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = CONNECTION_SET_PRIORITY,
+ .size_in = sizeof(connection_set_priority_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
+ uint32_t priority)
+{
+ return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, false);
+}
+
+static int
+_hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name,
+ uint32_t priority)
+{
+ return _hc_connection_set_priority_internal(s, conn_id_or_name, priority, true);
+}
+
+#endif // WITH_POLICY
+
+static int
+_hc_connection_set_tags_internal(hc_sock_t * s, const char * conn_id_or_name,
+ policy_tags_t tags, bool async)
+{
+ int rc;
+ DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s",
+ conn_id_or_name, tags, BOOLSTR(async));
+ struct {
+ header_control_message hdr;
+ connection_set_tags_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = CONNECTION_SET_TAGS,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .tags = tags,
+ },
+ };
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_connection_set_tags] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = CONNECTION_SET_TAGS,
+ .size_in = sizeof(connection_set_tags_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name,
+ policy_tags_t tags)
+{
+ return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, false);
+}
+
+static int
+_hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name,
+ policy_tags_t tags)
+{
+ return _hc_connection_set_tags_internal(s, conn_id_or_name, tags, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * Routes
+ *----------------------------------------------------------------------------*/
+
+/* ROUTE CREATE */
+
+static int
+_hc_route_create_internal(hc_sock_t * socket, hc_route_t * route, bool async)
+{
+ char route_s[MAXSZ_HC_ROUTE];
+ int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
+ if (rc >= MAXSZ_HC_ROUTE)
+ WARN("[_hc_route_create] Unexpected truncation of route string");
+ if (rc < 0)
+ WARN("[_hc_route_create] Error building route string");
+ else
+ DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async));
+
+ if (!IS_VALID_FAMILY(route->family))
+ return -1;
+
+ struct {
+ header_control_message hdr;
+ add_route_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = ADD_ROUTE,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .address = route->remote_addr,
+ .cost = route->cost,
+ .addressType = (u8)map_to_addr_type[route->family],
+ .len = route->len,
+ }
+ };
+
+ /*
+ * The route commands expects the ID (or name that we don't use) as part of
+ * the symbolicOrConnid attribute.
+ */
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_route_create] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = ADD_ROUTE,
+ .size_in = sizeof(add_route_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_route_create(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_create_internal(s, route, false);
+}
+
+static int
+_hc_route_create_async(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_create_internal(s, route, true);
+}
+
+/* ROUTE DELETE */
+
+static int
+_hc_route_delete_internal(hc_sock_t * socket, hc_route_t * route, bool async)
+{
+ char route_s[MAXSZ_HC_ROUTE];
+ int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route);
+ if (rc >= MAXSZ_HC_ROUTE)
+ WARN("[_hc_route_delete] Unexpected truncation of route string");
+ DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async));
+
+ if (!IS_VALID_FAMILY(route->family))
+ return -1;
+
+ struct {
+ header_control_message hdr;
+ remove_route_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = REMOVE_ROUTE,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .address = route->remote_addr,
+ .addressType = (u8)map_to_addr_type[route->family],
+ .len = route->len,
+ }
+ };
+
+ /*
+ * The route commands expects the ID (or name that we don't use) as part of
+ * the symbolicOrConnid attribute.
+ */
+ snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = REMOVE_ROUTE,
+ .size_in = sizeof(remove_route_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_route_delete(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_delete_internal(s, route, false);
+}
+
+static int
+_hc_route_delete_async(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_delete_internal(s, route, true);
+}
+
+/* ROUTE LIST */
+
+static int
+_hc_route_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
+{
+ //DEBUG("[hc_route_list] async=%s", BOOLSTR(async));
+
+ struct {
+ header_control_message hdr;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = LIST_ROUTES,
+ .length = 0,
+ .seqNum = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = LIST_ROUTES,
+ .size_in = sizeof(list_routes_command),
+ .size_out = sizeof(hc_route_t),
+ .parse = (HC_PARSE)hc_route_parse,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+static int
+_hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_route_list_internal(s, pdata, false);
+}
+
+static int
+_hc_route_list_async(hc_sock_t * s)
+{
+ return _hc_route_list_internal(s, NULL, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * Face
+ *
+ * Face support is not directly available in hicn-light, but we can offer such
+ * an interface through a combination of listeners and connections. The code
+ * starts with some conversion functions between faces/listeners/connections.
+ *
+ * We also need to make sure that there always exist a (single) listener when a
+ * connection is created, and in the hICN face case, that there is a single
+ * connection attached to this listener.
+ *
+ *----------------------------------------------------------------------------*/
+
+/* FACE CREATE */
+
+static int
+_hc_face_create(hc_sock_t * socket, hc_face_t * face)
+{
+ hc_listener_t listener;
+ hc_listener_t * listener_found;
+
+ hc_connection_t connection;
+ hc_connection_t * connection_found;
+
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_create] Unexpected truncation of face string");
+ DEBUG("[hc_face_create] face=%s", face_s);
+
+ switch(face->face.type)
+ {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ if (hc_face_to_connection(face, &connection, true) < 0) {
+ ERROR("[hc_face_create] Could not convert face to connection.");
+ return -1;
+ }
+
+ /* Ensure we have a corresponding local listener */
+ if (hc_connection_to_local_listener(&connection, &listener) < 0) {
+ ERROR("[hc_face_create] Could not convert face to local listener.");
+ return -1;
+ }
+
+ if (_hc_listener_get(socket, &listener, &listener_found) < 0) {
+ ERROR("[hc_face_create] Could not retrieve listener");
+ return -1;
+ }
+
+ if (!listener_found) {
+ /* We need to create the listener if it does not exist */
+ if (_hc_listener_create(socket, &listener) < 0) {
+ ERROR("[hc_face_create] Could not create listener.");
+ free(listener_found);
+ return -1;
+ }
+ } else {
+ free(listener_found);
+ }
+
+ /* Create corresponding connection */
+ if (_hc_connection_create(socket, &connection) < 0) {
+ ERROR("[hc_face_create] Could not create connection.");
+ return -1;
+ }
+
+ /*
+ * Once the connection is created, we need to list all connections
+ * and compare with the current one to find the created face ID.
+ */
+ if (_hc_connection_get(socket, &connection, &connection_found) < 0) {
+ ERROR("[hc_face_create] Could not retrieve connection");
+ return -1;
+ }
+
+ if (!connection_found) {
+ ERROR("[hc_face_create] Could not find newly created connection.");
+ return -1;
+ }
+
+ face->id = connection_found->id;
+ free(connection_found);
+
+ break;
+
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ if (hc_face_to_listener(face, &listener) < 0) {
+ ERROR("Could not convert face to listener.");
+ return -1;
+ }
+ if (_hc_listener_create(socket, &listener) < 0) {
+ ERROR("[hc_face_create] Could not create listener.");
+ return -1;
+ }
+ return -1;
+ break;
+ default:
+ ERROR("[hc_face_create] Unknwon face type.");
+
+ return -1;
+ };
+
+ return 0;
+}
+
+static int
+_hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found)
+{
+ hc_listener_t listener;
+ hc_listener_t * listener_found;
+
+ hc_connection_t connection;
+ hc_connection_t * connection_found;
+
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_get] Unexpected truncation of face string");
+ DEBUG("[hc_face_get] face=%s", face_s);
+
+ switch(face->face.type)
+ {
+ case FACE_TYPE_HICN:
+ case FACE_TYPE_TCP:
+ case FACE_TYPE_UDP:
+ if (hc_face_to_connection(face, &connection, false) < 0)
+ return -1;
+ if (_hc_connection_get(socket, &connection, &connection_found) < 0)
+ return -1;
+ if (!connection_found) {
+ *face_found = NULL;
+ return 0;
+ }
+ *face_found = malloc(sizeof(hc_face_t));
+ hc_connection_to_face(connection_found, *face_found);
+ free(connection_found);
+ break;
+
+ case FACE_TYPE_HICN_LISTENER:
+ case FACE_TYPE_TCP_LISTENER:
+ case FACE_TYPE_UDP_LISTENER:
+ if (hc_face_to_listener(face, &listener) < 0)
+ return -1;
+ if (_hc_listener_get(socket, &listener, &listener_found) < 0)
+ return -1;
+ if (!listener_found) {
+ *face_found = NULL;
+ return 0;
+ }
+ *face_found = malloc(sizeof(hc_face_t));
+ hc_listener_to_face(listener_found, *face_found);
+ free(listener_found);
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+
+}
+
+/* FACE DELETE */
+
+static int
+_hc_face_delete(hc_sock_t * socket, hc_face_t * face)
+{
+ char face_s[MAXSZ_HC_FACE];
+ int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face);
+ if (rc >= MAXSZ_HC_FACE)
+ WARN("[hc_face_delete] Unexpected truncation of face string");
+ DEBUG("[hc_face_delete] face=%s", face_s);
+
+ hc_connection_t connection;
+ if (hc_face_to_connection(face, &connection, false) < 0) {
+ ERROR("[hc_face_delete] Could not convert face to connection.");
+ return -1;
+ }
+
+ if (_hc_connection_delete(socket, &connection) < 0) {
+ ERROR("[hc_face_delete] Error removing connection");
+ return -1;
+ }
+
+ /* If this is the last connection attached to the listener, remove it */
+
+ hc_data_t * connections;
+ hc_listener_t listener = {{0}};
+
+ /*
+ * Ensure we have a corresponding local listener
+ * NOTE: hc_face_to_listener is not appropriate
+ */
+ if (hc_connection_to_local_listener(&connection, &listener) < 0) {
+ ERROR("[hc_face_create] Could not convert face to local listener.");
+ return -1;
+ }
+#if 1
+ /*
+ * The name is generated to prepare listener creation, we need it to be
+ * empty for deletion. The id should not need to be reset though.
+ */
+ listener.id = 0;
+ memset(listener.name, 0, sizeof(listener.name));
+#endif
+ if (_hc_connection_list(socket, &connections) < 0) {
+ ERROR("[hc_face_delete] Error getting the list of listeners");
+ return -1;
+ }
+
+ bool delete = true;
+ foreach_connection(c, connections) {
+ if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == 0) &&
+ (c->local_port == listener.local_port) &&
+ (strcmp(c->interface_name, listener.interface_name) == 0)) {
+ delete = false;
+ }
+ }
+
+ if (delete) {
+ if (_hc_listener_delete(socket, &listener) < 0) {
+ ERROR("[hc_face_delete] Error removing listener");
+ return -1;
+ }
+ }
+
+ hc_data_free(connections);
+
+ return 0;
+
+
+}
+
+/* FACE LIST */
+
+static int
+_hc_face_list(hc_sock_t * socket, hc_data_t ** pdata)
+{
+ hc_data_t * connection_data;
+ hc_face_t face;
+
+ //DEBUG("[hc_face_list]");
+
+ if (_hc_connection_list(socket, &connection_data) < 0) {
+ ERROR("[hc_face_list] Could not list connections.");
+ return -1;
+ }
+
+ hc_data_t * face_data = hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL);
+ foreach_connection(c, connection_data) {
+ if (hc_connection_to_face(c, &face) < 0) {
+ ERROR("[hc_face_list] Could not convert connection to face.");
+ goto ERR;
+ }
+ hc_data_push(face_data, &face);
+ }
+
+ *pdata = face_data;
+ hc_data_free(connection_data);
+ return 0;
+
+ERR:
+ hc_data_free(connection_data);
+ return -1;
+}
+
+static int
+_hc_face_list_async(hc_sock_t * socket)
+{
+ struct {
+ header_control_message hdr;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = LIST_CONNECTIONS,
+ .length = 0,
+ .seqNum = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = LIST_CONNECTIONS,
+ .size_in = sizeof(list_connections_command),
+ .size_out = sizeof(hc_face_t),
+ .parse = (HC_PARSE)hc_connection_parse_to_face,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, true);
+}
+
+static int
+_hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
+ face_state_t admin_state)
+{
+ return hc_connection_set_admin_state(s, conn_id_or_name, admin_state);
+}
+
+#ifdef WITH_POLICY
+static int
+_hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name,
+ uint32_t priority)
+{
+ return hc_connection_set_priority(s, conn_id_or_name, priority);
+}
+
+static int
+_hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name,
+ policy_tags_t tags)
+{
+ return hc_connection_set_tags(s, conn_id_or_name, tags);
+}
+#endif // WITH_POLICY
+
+/*----------------------------------------------------------------------------*
+ * Punting
+ *----------------------------------------------------------------------------*/
+
+static int
+_hc_punting_create_internal(hc_sock_t * socket, hc_punting_t * punting, bool async)
+{
+ int rc;
+
+ if (hc_punting_validate(punting) < 0)
+ return -1;
+
+ struct {
+ header_control_message hdr;
+ add_punting_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = ADD_PUNTING,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .address = punting->prefix,
+ .addressType = (u8)map_to_addr_type[punting->family],
+ .len = punting->prefix_len,
+ }
+ };
+ rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", punting->face_id);
+ if (rc >= SYMBOLIC_NAME_LEN)
+ WARN("[_hc_punting_create] Unexpected truncation of symbolic name string");
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = ADD_PUNTING,
+ .size_in = sizeof(add_punting_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
+{
+ return _hc_punting_create_internal(s, punting, false);
+}
+
+static int
+_hc_punting_create_async(hc_sock_t * s, hc_punting_t * punting)
+{
+ return _hc_punting_create_internal(s, punting, true);
+}
+
+static int
+_hc_punting_get(hc_sock_t * s, hc_punting_t * punting, hc_punting_t ** punting_found)
+{
+ ERROR("hc_punting_get not (yet) implemented.");
+ return -1;
+}
+
+static int
+_hc_punting_delete(hc_sock_t * s, hc_punting_t * punting)
+{
+ ERROR("hc_punting_delete not (yet) implemented.");
+ return -1;
+}
+
+static int
+_hc_punting_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ ERROR("hc_punting_list not (yet) implemented.");
+ return -1;
+}
+
+
+/*----------------------------------------------------------------------------*
+ * Cache
+ *----------------------------------------------------------------------------*/
+
+static int
+_hc_cache_set_store_internal(hc_sock_t * socket, int enabled, bool async)
+{
+ struct {
+ header_control_message hdr;
+ cache_store_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = CACHE_STORE,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .activate = enabled,
+ }
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = CACHE_STORE,
+ .size_in = sizeof(cache_store_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_cache_set_store(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_store_internal(s, enabled, false);
+}
+
+static int
+_hc_cache_set_store_async(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_store_internal(s, enabled, true);
+}
+
+static int
+_hc_cache_set_serve_internal(hc_sock_t * socket, int enabled, bool async)
+{
+ struct {
+ header_control_message hdr;
+ cache_serve_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = CACHE_SERVE,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .activate = enabled,
+ }
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_SET,
+ .cmd_id = CACHE_SERVE,
+ .size_in = sizeof(cache_serve_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_cache_set_serve(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_serve_internal(s, enabled, false);
+}
+
+static int
+_hc_cache_set_serve_async(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_serve_internal(s, enabled, true);
+}
+
+/*----------------------------------------------------------------------------*
+ * Strategy
+ *----------------------------------------------------------------------------*/
+
+// per prefix
+static int
+_hc_strategy_set(hc_sock_t * s /* XXX */)
+{
+ return 0;
+}
+
+/* How to retrieve that from the forwarder ? */
+static const char * strategies[] = {
+ "random",
+ "load_balancer",
+};
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
+
+static int
+_hc_strategy_list(hc_sock_t * s, hc_data_t ** data)
+{
+ int rc;
+
+ *data = hc_data_create(0, sizeof(hc_strategy_t), NULL);
+
+ for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) {
+ hc_strategy_t * strategy = (hc_strategy_t*)hc_data_get_next(*data);
+ if (!strategy)
+ return -1;
+ rc = snprintf(strategy->name, MAXSZ_HC_STRATEGY, "%s", strategies[i]);
+ if (rc >= MAXSZ_HC_STRATEGY)
+ WARN("[hc_strategy_list] Unexpected truncation of strategy name string");
+ (*data)->size++;
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*
+ * WLDR
+ *----------------------------------------------------------------------------*/
+
+// per connection
+static int
+_hc_wldr_set(hc_sock_t * s /* XXX */)
+{
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*
+ * MAP-Me
+ *----------------------------------------------------------------------------*/
+
+static int
+_hc_mapme_set(hc_sock_t * s, int enabled)
+{
+ return 0;
+}
+
+static int
+_hc_mapme_set_discovery(hc_sock_t * s, int enabled)
+{
+ return 0;
+}
+
+static int
+_hc_mapme_set_timescale(hc_sock_t * s, double timescale)
+{
+ return 0;
+}
+
+static int
+_hc_mapme_set_retx(hc_sock_t * s, double timescale)
+{
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*
+ * Policy
+ *----------------------------------------------------------------------------*/
+
+#ifdef WITH_POLICY
+
+/* POLICY CREATE */
+
+static int
+_hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async)
+{
+ if (!IS_VALID_FAMILY(policy->family))
+ return -1;
+
+ struct {
+ header_control_message hdr;
+ add_policy_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = ADD_POLICY,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .address = policy->remote_addr,
+ .addressType = (u8)map_to_addr_type[policy->family],
+ .len = policy->len,
+ .policy = policy->policy,
+ }
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_CREATE,
+ .cmd_id = ADD_POLICY,
+ .size_in = sizeof(add_policy_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_create_internal(s, policy, false);
+}
+
+static int
+_hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_create_internal(s, policy, true);
+}
+
+/* POLICY DELETE */
+
+static int
+_hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async)
+{
+ if (!IS_VALID_FAMILY(policy->family))
+ return -1;
+
+ struct {
+ header_control_message hdr;
+ remove_policy_command payload;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = REMOVE_POLICY,
+ .length = 1,
+ .seqNum = 0,
+ },
+ .payload = {
+ .address = policy->remote_addr,
+ .addressType = (u8)map_to_addr_type[policy->family],
+ .len = policy->len,
+ }
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_DELETE,
+ .cmd_id = REMOVE_POLICY,
+ .size_in = sizeof(remove_policy_command),
+ .size_out = 0,
+ .parse = NULL,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+static int
+_hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_delete_internal(s, policy, false);
+}
+
+static int
+_hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_delete_internal(s, policy, true);
+}
+
+/* POLICY LIST */
+
+static int
+_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async)
+{
+ struct {
+ header_control_message hdr;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = LIST_POLICIES,
+ .length = 0,
+ .seqNum = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = LIST_POLICIES,
+ .size_in = sizeof(list_policies_command),
+ .size_out = sizeof(hc_policy_t),
+ .parse = (HC_PARSE)hc_policy_parse,
+ };
+
+ return _hc_execute_command(socket, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+static int
+_hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_policy_list_internal(s, pdata, false);
+}
+
+static int
+_hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_policy_list_internal(s, pdata, true);
+}
+
+#endif /* WITH_POLICY */
+
+static hc_sock_t hc_sock_light_interface = (hc_sock_t) {
+ .hc_sock_get_next_seq = _hc_sock_light_get_next_seq,
+ .hc_sock_set_nonblocking = _hc_sock_light_set_nonblocking,
+ .hc_sock_get_fd = _hc_sock_light_get_fd,
+ .hc_sock_connect = _hc_sock_light_connect,
+ .hc_sock_get_available = _hc_sock_light_get_available,
+ .hc_sock_send = _hc_sock_light_send,
+ .hc_sock_recv = _hc_sock_light_recv,
+ .hc_sock_process = _hc_sock_light_process,
+ .hc_sock_callback = _hc_sock_light_callback,
+ .hc_sock_reset = _hc_sock_light_reset,
+ .hc_sock_free = _hc_sock_light_free,
+ .hc_listener_create = _hc_listener_create,
+ .hc_listener_create_async = _hc_listener_create_async,
+ .hc_listener_get = _hc_listener_get,
+ .hc_listener_delete = _hc_listener_delete,
+ .hc_listener_delete_async = _hc_listener_delete_async,
+ .hc_listener_list = _hc_listener_list,
+ .hc_listener_list_async = _hc_listener_list_async,
+ .hc_connection_create = _hc_connection_create,
+ .hc_connection_create_async = _hc_connection_create_async,
+ .hc_connection_get = _hc_connection_get,
+ .hc_connection_update_by_id = _hc_connection_update_by_id,
+ .hc_connection_update = _hc_connection_update,
+ .hc_connection_delete = _hc_connection_delete,
+ .hc_connection_delete_async = _hc_connection_delete_async,
+ .hc_connection_list = _hc_connection_list,
+ .hc_connection_list_async = _hc_connection_list_async,
+ .hc_connection_set_admin_state = _hc_connection_set_admin_state,
+ .hc_connection_set_admin_state_async = _hc_connection_set_admin_state_async,
+
+#ifdef WITH_POLICY
+ .hc_connection_set_priority = _hc_connection_set_priority,
+ .hc_connection_set_priority_async = _hc_connection_set_priority_async,
+ .hc_connection_set_tags = _hc_connection_set_tags,
+ .hc_connection_set_tags_async = _hc_connection_set_tags_async,
+#endif // WITH_POLICY
+
+ .hc_face_create = _hc_face_create,
+ .hc_face_get = _hc_face_get,
+ .hc_face_delete = _hc_face_delete,
+ .hc_face_list = _hc_face_list,
+ .hc_face_list_async = _hc_face_list_async,
+ .hc_face_set_admin_state = _hc_face_set_admin_state,
+
+#ifdef WITH_POLICY
+ .hc_face_set_priority = _hc_face_set_priority,
+ .hc_face_set_tags = _hc_face_set_tags,
+#endif // WITH_POLICY
+
+ .hc_route_create = _hc_route_create,
+ .hc_route_create_async = _hc_route_create_async,
+ .hc_route_delete = _hc_route_delete,
+ .hc_route_delete_async = _hc_route_delete_async,
+ .hc_route_list = _hc_route_list,
+ .hc_route_list_async = _hc_route_list_async,
+
+ .hc_punting_create = _hc_punting_create,
+ .hc_punting_create_async = _hc_punting_create_async,
+ .hc_punting_get = _hc_punting_get,
+ .hc_punting_delete = _hc_punting_delete,
+ .hc_punting_list = _hc_punting_list,
+
+ .hc_cache_set_store = _hc_cache_set_store,
+ .hc_cache_set_store_async = _hc_cache_set_store_async,
+ .hc_cache_set_serve = _hc_cache_set_serve,
+ .hc_cache_set_serve_async = _hc_cache_set_serve_async,
+
+ .hc_strategy_list = _hc_strategy_list,
+ .hc_strategy_set = _hc_strategy_set,
+ .hc_wldr_set = _hc_wldr_set,
+
+ .hc_mapme_set = _hc_mapme_set,
+ .hc_mapme_set_discovery = _hc_mapme_set_discovery,
+ .hc_mapme_set_timescale = _hc_mapme_set_timescale,
+ .hc_mapme_set_retx = _hc_mapme_set_retx,
+
+#ifdef WITH_POLICY
+ .hc_policy_create = _hc_policy_create,
+ .hc_policy_create_async = _hc_policy_create_async,
+ .hc_policy_delete = _hc_policy_delete,
+ .hc_policy_delete_async = _hc_policy_delete_async,
+ .hc_policy_list = _hc_policy_list,
+ .hc_policy_list_async = _hc_policy_list_async
+#endif // WITH_POLICY
+};
+
+// Public contructors
+
+hc_sock_t *
+_hc_sock_create_url(const char * url)
+{
+ hc_sock_light_t * s = malloc(sizeof(hc_sock_light_t));
+ if (!s)
+ goto ERR_MALLOC;
+
+ s->vft = hc_sock_light_interface;
+ s->url = url ? strdup(url) : NULL;
+
+ s->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (s->fd < 0)
+ goto ERR_SOCKET;
+
+ if (_hc_sock_light_reset((hc_sock_t*)s) < 0)
+ goto ERR_RESET;
+
+ s->seq = 0;
+ s->cur_request = NULL;
+
+ s->map = hc_sock_map_create();
+ if (!s->map)
+ goto ERR_MAP;
+
+ return (hc_sock_t*)(s);
+
+ //hc_sock_light_map_free(s->map);
+ERR_MAP:
+ERR_RESET:
+ if (s->url)
+ free(s->url);
+ close(s->fd);
+ERR_SOCKET:
+ free(s);
+ERR_MALLOC:
+ return NULL;
+}
+
+hc_sock_t *
+_hc_sock_create(void)
+{
+ return _hc_sock_create_url(NULL);
+}
diff --git a/ctrl/libhicnctrl/src/hicn_plugin_api.c b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
index 231c491ba..e59a2e41e 100644
--- a/ctrl/libhicnctrl/src/hicn_plugin_api.c
+++ b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c
@@ -18,6 +18,8 @@
* \brief Implementation of hICN control library API
*/
+#include "api_private.h"
+
#include <assert.h> // assert
#include <fcntl.h> // fcntl
#include <math.h> // log2
@@ -27,19 +29,10 @@
#include <sys/socket.h> // socket
#include <unistd.h> // close, fcntl
#include <vapi/vapi_safe.h>
-
-#include <hicn/ctrl/api.h>
-#include <hicn/ctrl/commands.h>
-#include <hicn/util/token.h>
-#include <strings.h>
#include <vapi/hicn.api.vapi.h>
#include <vapi/ip.api.vapi.h>
#include <vapi/udp.api.vapi.h>
#include <vapi/interface.api.vapi.h>
-#include <hicn/util/log.h>
-#include <hicn/util/map.h>
-#include <hicn/error.h>
-#include <vnet/ip/ip6_packet.h>
#if __GNUC__ >= 9
@@ -82,7 +75,10 @@ vapi_skc_ctx_t vapi_skc = {
/* TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, */
/* generic_snprintf); */
-struct hc_sock_s {
+struct hc_sock_vpp_s {
+ /* This must be the first element of the struct */
+ hc_sock_t vft;
+
vapi_ctx_t g_vapi_ctx_instance;
char *url;
int fd;
@@ -96,6 +92,9 @@ struct hc_sock_s {
bool async;
};
+typedef struct hc_sock_vpp_s hc_sock_vpp_t;
+
+#define TO_HC_SOCK_VPP(s) (hc_sock_vpp_t*)(s)
/******************************************************************************
* Message helper types and aliases
@@ -146,73 +145,11 @@ typedef struct __attribute__((__packed__)) {
} hc_msg_s;
/******************************************************************************
- * Control Data
- ******************************************************************************/
-
-hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size, data_callback_t complete_cb) {
- hc_data_t *data = malloc(sizeof(hc_data_t));
- if (!data) goto ERR_MALLOC;
-
- /* FIXME Could be NULL thanks to realloc provided size is 0 */
- data->in_element_size = in_element_size;
- data->out_element_size = out_element_size;
- data->size = 0;
- data->current = 0;
- data->complete = false;
- data->command_id = 0; // TODO this could also be a busy mark in the socket
- /* No callback needed in blocking code for instance */
- data->complete_cb = complete_cb;
-
- return data;
-
-ERR_MALLOC:
- return NULL;
-}
-
-void hc_data_free(hc_data_t *data) {
- if (data != NULL) {
- if (data->buffer) free(data->buffer);
- free(data);
- }
-}
-
-/******************************************************************************
* Control socket
******************************************************************************/
-/**
- * \brief Parse a connection URL into a sockaddr
- * \param [in] url - URL
- * \param [out] sa - Resulting struct sockaddr, expected zero'ed.
- * \return 0 if parsing succeeded, a negative error value otherwise.
- */
-int hc_sock_parse_url(const char *url, struct sockaddr *sa) {
- // NOT IMPLEMENTED
- return -1;
-}
-
-hc_sock_t *hc_sock_create_url(const char *url) {
- // NOT IMPLEMENTED
- return NULL;
-}
-
-hc_sock_t *hc_sock_create(void) {
- hc_sock_t *s = malloc(sizeof(hc_sock_t));
-
- if (!s) goto ERR_SOCK;
-
- memset(s, 0, sizeof(hc_sock_t));
-
- //By default the socket is blocking -- not async
- s->async = 0;
-
- return s;
-
-ERR_SOCK:
- return NULL;
-}
-
-void hc_sock_free(hc_sock_t *s) {
+static void _hc_sock_vpp_free(hc_sock_t *socket) {
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
if (s->url) free(s->url);
close(s->fd);
free(s);
@@ -221,19 +158,21 @@ void hc_sock_free(hc_sock_t *s) {
vapi_skc.g_vapi_ctx_instance = NULL;
}
-int hc_sock_get_next_seq(hc_sock_t *s) {
+static int _hc_sock_vpp_get_next_seq(hc_sock_t *socket) {
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
return vapi_gen_req_context(s->g_vapi_ctx_instance);
}
-int hc_sock_set_nonblocking(hc_sock_t *s) {
+static int _hc_sock_vpp_set_nonblocking(hc_sock_t *socket) {
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
s->async = 1;
return 0;
}
-int hc_sock_get_fd(hc_sock_t *s) { return 1; }
-
-int hc_sock_connect(hc_sock_t *s) {
+static int _hc_sock_vpp_get_fd(hc_sock_t *s) { return 1; }
+static int _hc_sock_vpp_connect(hc_sock_t *socket) {
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_error_e rv = vapi_connect_safe(&s->g_vapi_ctx_instance, s->async);
if (rv != VAPI_OK)
goto ERR_CONNECT;
@@ -245,25 +184,35 @@ ERR_CONNECT:
return -1;
}
-int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq) {
+static int _hc_sock_vpp_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, int seq) {
return -1;
}
-int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size) {
+static int _hc_sock_vpp_get_available(hc_sock_t *s, u8 **buffer, size_t *size) {
// NOT IMPLEMENTED
return -1;
}
-int hc_sock_recv(hc_sock_t *s) {
+static int _hc_sock_vpp_recv(hc_sock_t *s) {
// NOT IMPLEMENTED
return -1;
}
-int hc_sock_process(hc_sock_t *s, hc_data_t **pdata) {
+static int _hc_sock_vpp_process(hc_sock_t *s, hc_data_t **pdata) {
//NOT IMPLEMENTED
return -1;
}
+static int _hc_sock_vpp_callback(hc_sock_t * socket, hc_data_t ** pdata) {
+ // NOT IMPLEMENTED
+ return -1;
+}
+
+static int _hc_sock_vpp_reset(hc_sock_t * socket) {
+ // NOT IMPLEMENTED
+ return -1;
+}
+
/******************************************************************************
* Command-specific structures and functions
******************************************************************************/
@@ -275,23 +224,18 @@ int hc_sock_process(hc_sock_t *s, hc_data_t **pdata) {
/* LISTENER CREATE */
-int _hc_listener_create(hc_sock_t *s, hc_listener_t *listener, bool async) {
+static int _hc_listener_create(hc_sock_t *s, hc_listener_t *listener) {
// NOT IMPLEMENTED
return -1;
}
-int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) {
- // NOT IMPLEMENTED
- return -1;
-}
-
-int hc_listener_create_async(hc_sock_t *s, hc_listener_t *listener) {
+static int _hc_listener_create_async(hc_sock_t *s, hc_listener_t *listener) {
// NOT IMPLEMENTED
return -1;
}
/* LISTENER GET */
-int hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
+static int _hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
hc_listener_t **listener_found) {
// NOT IMPLEMENTED
return -1;
@@ -299,21 +243,21 @@ int hc_listener_get(hc_sock_t *s, hc_listener_t *listener,
/* LISTENER DELETE */
-int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) {
+static int _hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) {
// NOT IMPLEMENTED
return -1;
}
-int hc_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) {
+static int _hc_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) {
// NOT IMPLEMENTED
return -1;
}
-vapi_error_e process_ip_info(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_ip_address_details *reply) {
+static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx,
+ void *callback_ctx,
+ vapi_error_e rv,
+ bool is_last,
+ vapi_payload_ip_address_details *reply) {
if (is_last)
return 0;
@@ -349,10 +293,11 @@ typedef struct {
char interface_name[INTERFACE_LEN];
} hc_vapi_interface_t;
-vapi_error_e listener_list_complete_cb (struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
+static vapi_error_e listener_list_complete_cb (
+ struct vapi_ctx_s *ctx,
+ void *callback_ctx,
+ vapi_error_e rv,
+ bool is_last,
vapi_payload_sw_interface_details *reply) {
if (reply == NULL || rv != VAPI_OK)
@@ -384,7 +329,8 @@ vapi_error_e listener_list_complete_cb (struct vapi_ctx_s *ctx,
/* LISTENER LIST */
-int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) {
+static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) {
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
int retval = VAPI_OK;
vapi_lock();
vapi_msg_sw_interface_dump *hicnp_msg;
@@ -456,6 +402,7 @@ int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) {
retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info, data2);
for (size_t j = index; j < data2->current; j++) {
memcpy(((hc_listener_t *)(data2->buffer))[j].interface_name, ((hc_vapi_interface_t*)(data->buffer))[i].interface_name, INTERFACE_LEN);
+ ((hc_listener_t *)(data2->buffer))[j].type = CONNECTION_TYPE_HICN;
}
if (retval) goto CLEAN;
@@ -475,148 +422,104 @@ FREE_DATA:
return retval;
}
-int hc_listener_list_async(hc_sock_t *s, hc_data_t **pdata) {
- // NOT IMPLEMENTED
- return -1;
-}
-
-/* LISTENER VALIDATE */
-
-int hc_listener_validate(const hc_listener_t *listener) {
- // NOT IMPLEMENTED
- return -1;
-}
-
-/* LISTENER CMP */
-
-int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2) {
- // NOT IMPLEMENTED
- return -1;
-}
-
-/* LISTENER PARSE */
-
-int hc_listener_parse(void *in, hc_listener_t *listener) {
+static int _hc_listener_list_async(hc_sock_t *s, hc_data_t **pdata) {
// NOT IMPLEMENTED
return -1;
}
-GENERATE_FIND(listener)
-
-/* LISTENER SNPRINTF */
-
-/* /!\ Please update constants in header file upon changes */
-int
-hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener)
-{
- char local[MAXSZ_URL];
- int rc;
- rc = url_snprintf(local, MAXSZ_URL,
- listener->family, &listener->local_addr, listener->local_port);
- if (rc >= MAXSZ_URL)
- WARN("[hc_listener_snprintf] Unexpected truncation of URL string");
- if (rc < 0)
- return rc;
-
- return snprintf(s, size, "%s %s", listener->interface_name, local);
-}
-
/*----------------------------------------------------------------------------*
* CONNECTION
*----------------------------------------------------------------------------*/
/* CONNECTION CREATE */
-int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_create(hc_sock_t *s, hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
-int hc_connection_create_async(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_create_async(hc_sock_t *s, hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
/* CONNECTION GET */
-int hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
+static int _hc_connection_get(hc_sock_t *s, hc_connection_t *connection,
hc_connection_t **connection_found) {
// NOT IMPLEMENTED
return -1;
}
+static int _hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, hc_connection_t *connection) {
+ // Not implemented
+ return -1;
+}
+
+static int _hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, hc_connection_t *connection_updated) {
+ // Not implemented
+ return -1;
+}
+
/* CONNECTION DELETE */
-int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
-int hc_connection_delete_async(hc_sock_t *s, hc_connection_t *connection) {
+static int _hc_connection_delete_async(hc_sock_t *s, hc_connection_t *connection) {
// NOT IMPLEMENTED
return -1;
}
/* CONNECTION LIST */
-int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) {
+static int _hc_connection_list(hc_sock_t *s, hc_data_t **pdata) {
// NOT IMPLEMENTED
return -1;
}
-int hc_connection_list_async(hc_sock_t *s, hc_data_t **pdata) {
+static int _hc_connection_list_async(hc_sock_t *s, hc_data_t **pdata) {
// NOT IMPLEMENTED
return -1;
}
-/* CONNECTION VALIDATE */
+/* CONNECTION SET ADMIN STATE */
-int hc_connection_validate(const hc_connection_t *connection) {
+static int _hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
+ face_state_t state) {
// NOT IMPLEMENTED
return -1;
}
-/* CONNECTION CMP */
-
-/*
- * hICN light uses ports even for hICN connections, but their value is ignored.
- * As connections are specific to hicn-light, we can safely use IP and ports for
- * comparison independently of the face type.
- */
-int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2) {
+static int _hc_connection_set_admin_state_async(hc_sock_t *s,
+ const char *conn_id_or_name,
+ face_state_t state) {
// NOT IMPLEMENTED
return -1;
}
-/* CONNECTION PARSE */
+#ifdef WITH_POLICY
-int hc_connection_parse(void *in, hc_connection_t *connection) {
+static int _hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
// NOT IMPLEMENTED
return -1;
}
-GENERATE_FIND(connection)
-
-/* CONNECTION SNPRINTF */
-
-/* /!\ Please update constants in header file upon changes */
-int hc_connection_snprintf(char *s, size_t size,
- const hc_connection_t *connection) {
+static int _hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
// NOT IMPLEMENTED
return -1;
}
-/* CONNECTION SET ADMIN STATE */
+#endif // WITH_POLICY
-int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name,
- face_state_t state) {
+static int _hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
// NOT IMPLEMENTED
return -1;
}
-int hc_connection_set_admin_state_async(hc_sock_t *s,
- const char *conn_id_or_name,
- face_state_t state) {
+static int _hc_connection_set_tags_async(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
// NOT IMPLEMENTED
return -1;
}
@@ -625,7 +528,7 @@ int hc_connection_set_admin_state_async(hc_sock_t *s,
* Routes
*----------------------------------------------------------------------------*/
-vapi_error_e create_udp_tunnel_cb( vapi_ctx_t ctx,
+static vapi_error_e create_udp_tunnel_cb( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
@@ -643,7 +546,7 @@ vapi_error_e create_udp_tunnel_cb( vapi_ctx_t ctx,
}
/* ROUTE CREATE */
-vapi_error_e parse_route_create( vapi_ctx_t ctx,
+static vapi_error_e parse_route_create( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
@@ -657,7 +560,7 @@ vapi_error_e parse_route_create( vapi_ctx_t ctx,
return reply->retval;
}
-vapi_error_e hicn_enable_cb( vapi_ctx_t ctx,
+static vapi_error_e hicn_enable_cb( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
@@ -668,9 +571,10 @@ vapi_error_e hicn_enable_cb( vapi_ctx_t ctx,
return reply->retval;
}
-int _hc_route_create(hc_sock_t *s, hc_route_t *route, bool async) {
+static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
int ret;
vapi_lock();
@@ -786,16 +690,16 @@ done:
return ret;
}
-int hc_route_create(hc_sock_t *s, hc_route_t *route) {
- return _hc_route_create(s, route, false);
+static int _hc_route_create(hc_sock_t *s, hc_route_t *route) {
+ return _hc_route_create_internal(s, route, false);
}
-int hc_route_create_async(hc_sock_t *s, hc_route_t *route) {
- return _hc_route_create(s, route, true);
+static int _hc_route_create_async(hc_sock_t *s, hc_route_t *route) {
+ return _hc_route_create_internal(s, route, true);
}
/* ROUTE DELETE */
-vapi_error_e parse_route_delete( vapi_ctx_t ctx,
+static vapi_error_e parse_route_delete( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
@@ -806,9 +710,11 @@ vapi_error_e parse_route_delete( vapi_ctx_t ctx,
return reply->retval;
}
-int _hc_route_delete(hc_sock_t *s, hc_route_t *route, bool async) {
+static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route, bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
+
vapi_lock();
vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
@@ -862,15 +768,15 @@ int _hc_route_delete(hc_sock_t *s, hc_route_t *route, bool async) {
return ret;
}
-int hc_route_delete(hc_sock_t *s, hc_route_t *route) {
- return _hc_route_delete(s, route, false);
+static int _hc_route_delete(hc_sock_t *s, hc_route_t *route) {
+ return _hc_route_delete_internal(s, route, false);
}
-int hc_route_delete_async(hc_sock_t *s, hc_route_t *route) {
- return _hc_route_delete(s, route, true);
+static int _hc_route_delete_async(hc_sock_t *s, hc_route_t *route) {
+ return _hc_route_delete_internal(s, route, true);
}
-vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
+static vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
@@ -905,7 +811,7 @@ vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
return rv;
}
-int fill_face_with_info(hc_face_t * face, vapi_type_fib_path *path, hc_sock_t *s) {
+static int _fill_face_with_info(hc_face_t * face, vapi_type_fib_path *path, hc_sock_t *s) {
switch(path->type){
case FIB_API_PATH_FLAG_NONE:
{
@@ -927,6 +833,8 @@ int fill_face_with_info(hc_face_t * face, vapi_type_fib_path *path, hc_sock_t *s
{
face->face.type = FACE_TYPE_UDP;
face->face.netdevice.index = clib_net_to_host_u32(path->nh.obj_id);
+ // Let's make the compiler happy
+ (void)parse_udp_encap_list;
//vapi_msg_udp_encap_dump *msg;
//msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance);
//vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, face);
@@ -944,7 +852,7 @@ typedef struct hicn_route_socket_s {
hc_sock_t *s;
} hicn_route_socket_t;
-vapi_error_e parse_route_list( vapi_ctx_t ctx,
+static vapi_error_e parse_route_list( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
@@ -964,11 +872,11 @@ vapi_error_e parse_route_list( vapi_ctx_t ctx,
if(ip46_address_is_ip4((ip46_address_t *)&(route->remote_addr)) &&
memcmp(route->remote_addr.v4.as_u8, reply->route.prefix.address.un.ip4, sizeof(ip4_address_t)) == 0 &&
route->len == reply->route.prefix.len && route->face_id == ~0) {
- fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
found = true;
} else if (memcmp(route->remote_addr.v6.as_u8, reply->route.prefix.address.un.ip6, sizeof(ip6_address_t)) == 0 &&
route->len == reply->route.prefix.len && route->face_id == ~0) {
- fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
found = true;
}
}
@@ -977,7 +885,7 @@ vapi_error_e parse_route_list( vapi_ctx_t ctx,
return rv;
}
-vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
+static vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
@@ -1018,7 +926,8 @@ vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
return rv;
}
-int _hc_route_list(hc_sock_t *s, hc_data_t **pdata, bool async) {
+static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, bool async) {
+ hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket);
vapi_lock();
vapi_msg_hicn_api_routes_dump *msg;
@@ -1052,7 +961,7 @@ int _hc_route_list(hc_sock_t *s, hc_data_t **pdata, bool async) {
hicn_route_socket_t ctx = {
.data = data,
- .s = s,
+ .s = socket,
};
ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx);
@@ -1078,29 +987,12 @@ int _hc_route_list(hc_sock_t *s, hc_data_t **pdata, bool async) {
return ret;
}
-int hc_route_list(hc_sock_t *s, hc_data_t **pdata) {
- return _hc_route_list(s, pdata, false);
-}
-
-int hc_route_list_async(hc_sock_t *s) {
- return _hc_route_list(s, NULL, true);
+static int _hc_route_list(hc_sock_t *s, hc_data_t **pdata) {
+ return _hc_route_list_internal(s, pdata, false);
}
-/* ROUTE SNPRINTF */
-
-/* /!\ Please update constants in header file upon changes */
-int hc_route_snprintf(char *s, size_t size, hc_route_t *route) {
- /* interface cost prefix length */
-
- char prefix[MAXSZ_IP_ADDRESS];
- int rc;
-
- rc = ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr,
- route->family);
- if (rc < 0) return rc;
-
- return snprintf(s, size, "%*d %*d %s %*d", MAXSZ_FACE_ID, route->face_id,
- MAXSZ_COST, route->cost, prefix, MAXSZ_LEN, route->len);
+static int _hc_route_list_async(hc_sock_t *s) {
+ return _hc_route_list_internal(s, NULL, true);
}
/*----------------------------------------------------------------------------*
@@ -1116,176 +1008,108 @@ int hc_route_snprintf(char *s, size_t size, hc_route_t *route) {
*
*----------------------------------------------------------------------------*/
-/* FACE -> LISTENER */
-
-int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener) {
- const face_t *f = &face->face;
-
- switch (f->type) {
- case FACE_TYPE_HICN_LISTENER:
- break;
- case FACE_TYPE_TCP_LISTENER:
- break;
- case FACE_TYPE_UDP_LISTENER:
- break;
- default:
- return -1;
- }
- return -1; /* XXX Not implemented */
-}
-
-/* LISTENER -> FACE */
-
-int hc_listener_to_face(const hc_listener_t *listener, hc_face_t *face) {
- return -1; /* XXX Not implemented */
-}
-
-/* FACE -> CONNECTION */
-
-int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection,
- bool generate_name) {
- return 0;
-}
-
-/* CONNECTION -> FACE */
-
-int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face) {
- return 0;
-}
-
-/* CONNECTION -> LISTENER */
-
-int hc_connection_to_local_listener(const hc_connection_t *connection,
- hc_listener_t *listener) {
- return 0;
-}
-
-int hc_face_create(hc_sock_t *s, hc_face_t *face) {
+static int _hc_face_create(hc_sock_t *s, hc_face_t *face) {
ERROR("Face creation implemented.");
return -1;
}
-int hc_face_delete(hc_sock_t *s, hc_face_t *face) {
+static int _hc_face_get(hc_sock_t * socket, hc_face_t * face, hc_face_t ** face_found) {
+ ERROR("Face deletion not implemented.");
+ return -1;
+}
+static int _hc_face_delete(hc_sock_t *s, hc_face_t *face) {
ERROR("Face deletion not implemented.");
return -1;
}
/* FACE LIST */
-int hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
-
-ERROR("Face list not implemented.");
-return -1;
+static int _hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
+ ERROR("Face list not implemented.");
+ return -1;
}
-int hc_connection_parse_to_face(void *in, hc_face_t *face) { return 0; }
-
-int hc_face_list_async(hc_sock_t *s)
-{
+static int _hc_face_list_async(hc_sock_t *s) {
return 0;
}
-/* /!\ Please update constants in header file upon changes */
-int hc_face_snprintf(char *s, size_t size, hc_face_t *face) { return 0; }
-
-int hc_face_set_admin_state(
+static int _hc_face_set_admin_state(
hc_sock_t *s, const char *conn_id_or_name, // XXX wrong identifier
face_state_t admin_state) {
return 0;
}
+#ifdef WITH_POLICY
+static int _hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority) {
+ ERROR("Face set priority not implemented.");
+ return -1;
+}
+
+static int _hc_face_set_tags(hc_sock_t * s, const char * conn_id_or_name, policy_tags_t tags) {
+ ERROR("Face set tags not implemented.");
+ return -1;
+}
+#endif // WITH_POLICY
+
/*----------------------------------------------------------------------------*
* Punting
*----------------------------------------------------------------------------*/
-int _hc_punting_create(hc_sock_t *s, hc_punting_t *punting, bool async) {
- return 0;
+static int _hc_punting_create_internal(hc_sock_t *s, hc_punting_t *punting, bool async) {
+ return -1;
}
-int hc_punting_create(hc_sock_t *s, hc_punting_t *punting) {
- return _hc_punting_create(s, punting, false);
+static int _hc_punting_create(hc_sock_t *s, hc_punting_t *punting) {
+ return _hc_punting_create_internal(s, punting, false);
}
-int hc_punting_create_async(hc_sock_t *s, hc_punting_t *punting) {
- return _hc_punting_create(s, punting, true);
+static int _hc_punting_create_async(hc_sock_t *s, hc_punting_t *punting) {
+ return _hc_punting_create_internal(s, punting, true);
}
-int hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
+static int _hc_punting_get(hc_sock_t *s, hc_punting_t *punting,
hc_punting_t **punting_found) {
ERROR("hc_punting_get not (yet) implemented.");
return -1;
}
-int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting) {
+static int _hc_punting_delete(hc_sock_t *s, hc_punting_t *punting) {
ERROR("hc_punting_delete not (yet) implemented.");
return -1;
}
-int hc_punting_list(hc_sock_t *s, hc_data_t **pdata) {
+static int _hc_punting_list(hc_sock_t *s, hc_data_t **pdata) {
ERROR("hc_punting_list not (yet) implemented.");
return -1;
}
-int hc_punting_validate(const hc_punting_t *punting) {
- if (!IS_VALID_FAMILY(punting->family)) return -1;
-
- /*
- * We might use the zero value to add punting on all faces but this is not
- * (yet) implemented
- */
- if (punting->face_id == 0) {
- ERROR("Punting on all faces is not (yet) implemented.");
- return -1;
- }
-
- return 0;
-}
-
-int hc_punting_cmp(const hc_punting_t *p1, const hc_punting_t *p2) {
- return ((p1->face_id == p2->face_id) && (p1->family == p2->family) &&
- (ip_address_cmp(&p1->prefix, &p2->prefix, p1->family) == 0) &&
- (p1->prefix_len == p2->prefix_len))
- ? 0
- : -1;
-}
-
-int hc_punting_parse(void *in, hc_punting_t *punting) {
- ERROR("hc_punting_parse not (yet) implemented.");
- return -1;
-}
-
-int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting) {
- ERROR("hc_punting_snprintf not (yet) implemented.");
- return -1;
-}
-
/*----------------------------------------------------------------------------*
* Cache
*----------------------------------------------------------------------------*/
-int _hc_cache_set_store(hc_sock_t *s, int enabled, bool async) {
+static int _hc_cache_set_store_internal(hc_sock_t *s, int enabled, bool async) {
return 0;
}
-int hc_cache_set_store(hc_sock_t *s, int enabled) {
- return _hc_cache_set_store(s, enabled, false);
+static int _hc_cache_set_store(hc_sock_t *s, int enabled) {
+ return _hc_cache_set_store_internal(s, enabled, false);
}
-int hc_cache_set_store_async(hc_sock_t *s, int enabled) {
- return _hc_cache_set_store(s, enabled, true);
+static int _hc_cache_set_store_async(hc_sock_t *s, int enabled) {
+ return _hc_cache_set_store_internal(s, enabled, true);
}
-int _hc_cache_set_serve(hc_sock_t *s, int enabled, bool async) {
+static int _hc_cache_set_serve_internal(hc_sock_t *s, int enabled, bool async) {
return 0;
}
-int hc_cache_set_serve(hc_sock_t *s, int enabled) {
- return _hc_cache_set_serve(s, enabled, false);
+static int _hc_cache_set_serve(hc_sock_t *s, int enabled) {
+ return _hc_cache_set_serve_internal(s, enabled, false);
}
-int hc_cache_set_serve_async(hc_sock_t *s, int enabled) {
- return _hc_cache_set_serve(s, enabled, true);
+static int _hc_cache_set_serve_async(hc_sock_t *s, int enabled) {
+ return _hc_cache_set_serve_internal(s, enabled, true);
}
/*----------------------------------------------------------------------------*
@@ -1293,55 +1117,189 @@ int hc_cache_set_serve_async(hc_sock_t *s, int enabled) {
*----------------------------------------------------------------------------*/
// per prefix
-int hc_strategy_set(hc_sock_t *s /* XXX */) { return 0; }
-
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
+static int _hc_strategy_set(hc_sock_t *s /* XXX */) { return 0; }
-int hc_strategy_list(hc_sock_t *s, hc_data_t **data) {
+static int _hc_strategy_list(hc_sock_t *s, hc_data_t **data) {
return 0;
}
-/* /!\ Please update constants in header file upon changes */
-int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy) {
- return snprintf(s, size, "%s", strategy->name);
-}
-
/*----------------------------------------------------------------------------*
* WLDR
*----------------------------------------------------------------------------*/
// per connection
-int hc_wldr_set(hc_sock_t *s /* XXX */) { return 0; }
+static int _hc_wldr_set(hc_sock_t *s /* XXX */) { return 0; }
/*----------------------------------------------------------------------------*
* MAP-Me
*----------------------------------------------------------------------------*/
-int hc_mapme_set(hc_sock_t *s, int enabled) { return 0; }
+static int _hc_mapme_set(hc_sock_t *s, int enabled) { return 0; }
+
+static int _hc_mapme_set_discovery(hc_sock_t *s, int enabled) { return 0; }
+
+static int _hc_mapme_set_timescale(hc_sock_t *s, double timescale) { return 0; }
+
+static int _hc_mapme_set_retx(hc_sock_t *s, double timescale) { return 0; }
+
+/*----------------------------------------------------------------------------*
+ * Policy
+ *----------------------------------------------------------------------------*/
+
+#ifdef WITH_POLICY
-int hc_mapme_set_discovery(hc_sock_t *s, int enabled) { return 0; }
+/* POLICY CREATE */
-int hc_mapme_set_timescale(hc_sock_t *s, double timescale) { return 0; }
+static int _hc_policy_create_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) {
+ return -1;
+}
-int hc_mapme_set_retx(hc_sock_t *s, double timescale) { return 0; }
+static int
+_hc_policy_create(hc_sock_t * s, hc_policy_t * policy) {
+ return _hc_policy_create_internal(s, policy, false);
+}
-/* Useless function defined to prevent undefined reference */
-hc_connection_type_t
-connection_type_from_str(const char * str)
-{
- if (strcasecmp(str, "TCP") == 0)
- return CONNECTION_TYPE_TCP;
- else if (strcasecmp(str, "UDP") == 0)
- return CONNECTION_TYPE_UDP;
- else if (strcasecmp(str, "HICN") == 0)
- return CONNECTION_TYPE_HICN;
- else
- return CONNECTION_TYPE_UNDEFINED;
+static int _hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy) {
+ return _hc_policy_create_internal(s, policy, true);
}
-/*********************** Missing Symbol in vpp libraries *************************/
-u8 *
-format_vl_api_address_union (u8 * s, va_list * args)
-{
+/* POLICY DELETE */
+
+static int _hc_policy_delete_internal(hc_sock_t * socket, hc_policy_t * policy, bool async) {
+ return -1;
+}
+
+static int _hc_policy_delete(hc_sock_t * s, hc_policy_t * policy) {
+ return _hc_policy_delete_internal(s, policy, false);
+}
+
+static int _hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy) {
+ return _hc_policy_delete_internal(s, policy, true);
+}
+
+/* POLICY LIST */
+
+static int
+_hc_policy_list_internal(hc_sock_t * socket, hc_data_t ** pdata, bool async) {
+ return -1;
+}
+
+static int _hc_policy_list(hc_sock_t * s, hc_data_t ** pdata) {
+ return _hc_policy_list_internal(s, pdata, false);
+}
+
+static int _hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata) {
+ return _hc_policy_list_internal(s, pdata, true);
+}
+
+#endif /* WITH_POLICY */
+
+static hc_sock_t hc_sock_vpp_interface = (hc_sock_t) {
+ .hc_sock_get_next_seq = _hc_sock_vpp_get_next_seq,
+ .hc_sock_set_nonblocking = _hc_sock_vpp_set_nonblocking,
+ .hc_sock_get_fd = _hc_sock_vpp_get_fd,
+ .hc_sock_connect = _hc_sock_vpp_connect,
+ .hc_sock_get_available = _hc_sock_vpp_get_available,
+ .hc_sock_send = _hc_sock_vpp_send,
+ .hc_sock_recv = _hc_sock_vpp_recv,
+ .hc_sock_process = _hc_sock_vpp_process,
+ .hc_sock_callback = _hc_sock_vpp_callback,
+ .hc_sock_reset = _hc_sock_vpp_reset,
+ .hc_sock_free = _hc_sock_vpp_free,
+ .hc_listener_create = _hc_listener_create,
+ .hc_listener_create_async = _hc_listener_create_async,
+ .hc_listener_get = _hc_listener_get,
+ .hc_listener_delete = _hc_listener_delete,
+ .hc_listener_delete_async = _hc_listener_delete_async,
+ .hc_listener_list = _hc_listener_list,
+ .hc_listener_list_async = _hc_listener_list_async,
+ .hc_connection_create = _hc_connection_create,
+ .hc_connection_create_async = _hc_connection_create_async,
+ .hc_connection_get = _hc_connection_get,
+ .hc_connection_update_by_id = _hc_connection_update_by_id,
+ .hc_connection_update = _hc_connection_update,
+ .hc_connection_delete = _hc_connection_delete,
+ .hc_connection_delete_async = _hc_connection_delete_async,
+ .hc_connection_list = _hc_connection_list,
+ .hc_connection_list_async = _hc_connection_list_async,
+ .hc_connection_set_admin_state = _hc_connection_set_admin_state,
+ .hc_connection_set_admin_state_async = _hc_connection_set_admin_state_async,
+
+#ifdef WITH_POLICY
+ .hc_connection_set_priority = _hc_connection_set_priority,
+ .hc_connection_set_priority_async = _hc_connection_set_priority_async,
+ .hc_connection_set_tags = _hc_connection_set_tags,
+ .hc_connection_set_tags_async = _hc_connection_set_tags_async,
+#endif // WITH_POLICY
+
+ .hc_face_create = _hc_face_create,
+ .hc_face_get = _hc_face_get,
+ .hc_face_delete = _hc_face_delete,
+ .hc_face_list = _hc_face_list,
+ .hc_face_list_async = _hc_face_list_async,
+ .hc_face_set_admin_state = _hc_face_set_admin_state,
+
+#ifdef WITH_POLICY
+ .hc_face_set_priority = _hc_face_set_priority,
+ .hc_face_set_tags = _hc_face_set_tags,
+#endif // WITH_POLICY
+
+ .hc_route_create = _hc_route_create,
+ .hc_route_create_async = _hc_route_create_async,
+ .hc_route_delete = _hc_route_delete,
+ .hc_route_delete_async = _hc_route_delete_async,
+ .hc_route_list = _hc_route_list,
+ .hc_route_list_async = _hc_route_list_async,
+
+ .hc_punting_create = _hc_punting_create,
+ .hc_punting_create_async = _hc_punting_create_async,
+ .hc_punting_get = _hc_punting_get,
+ .hc_punting_delete = _hc_punting_delete,
+ .hc_punting_list = _hc_punting_list,
+
+ .hc_cache_set_store = _hc_cache_set_store,
+ .hc_cache_set_store_async = _hc_cache_set_store_async,
+ .hc_cache_set_serve = _hc_cache_set_serve,
+ .hc_cache_set_serve_async = _hc_cache_set_serve_async,
+
+ .hc_strategy_list = _hc_strategy_list,
+ .hc_strategy_set = _hc_strategy_set,
+ .hc_wldr_set = _hc_wldr_set,
+
+ .hc_mapme_set = _hc_mapme_set,
+ .hc_mapme_set_discovery = _hc_mapme_set_discovery,
+ .hc_mapme_set_timescale = _hc_mapme_set_timescale,
+ .hc_mapme_set_retx = _hc_mapme_set_retx,
+
+#ifdef WITH_POLICY
+ .hc_policy_create = _hc_policy_create,
+ .hc_policy_create_async = _hc_policy_create_async,
+ .hc_policy_delete = _hc_policy_delete,
+ .hc_policy_delete_async = _hc_policy_delete_async,
+ .hc_policy_list = _hc_policy_list,
+ .hc_policy_list_async = _hc_policy_list_async
+#endif // WITH_POLICY
+};
+
+hc_sock_t *_hc_sock_create_url(const char *url) {
+ // NOT IMPLEMENTED
return NULL;
}
+
+hc_sock_t *_hc_sock_create(void) {
+ hc_sock_vpp_t *s = malloc(sizeof(hc_sock_vpp_t));
+
+ if (!s) goto ERR_SOCK;
+
+ memset(s, 0, sizeof(hc_sock_vpp_t));
+
+ s->vft = hc_sock_vpp_interface;
+
+ // By default the socket is blocking -- not async
+ s->async = 0;
+
+ return (hc_sock_t *)(s);
+
+ERR_SOCK:
+ return NULL;
+} \ No newline at end of file
diff --git a/ctrl/sysrepo-plugins/CMakeLists.txt b/ctrl/sysrepo-plugins/CMakeLists.txt
index f1e1553dc..2412d5688 100644
--- a/ctrl/sysrepo-plugins/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/CMakeLists.txt
@@ -13,7 +13,7 @@
# limitations under the License.
#
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(hicn_sysrepo_plugin)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
diff --git a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
index 6be257656..5ba7045c1 100644
--- a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
@@ -20,7 +20,6 @@ set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
set (CMAKE_INSTALL_LIBDIR "/usr/lib")
-cmake_minimum_required(VERSION 3.5)
project(sysrepo-light-plugins)
# Cmake find modules
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
index 220809d71..85da0d3e9 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
@@ -20,7 +20,6 @@ set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
set (CMAKE_INSTALL_LIBDIR "/usr/lib")
-cmake_minimum_required(VERSION 3.5)
project(sysrepo-light-plugins)
# Cmake find modules
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
index a89936776..10e106f51 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
@@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5)
-
# Cmake find modules
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../cmake/Modules"
"${CMAKE_CURRENT_LIST_DIR}/../cmake/Modules"
diff --git a/extras/CMakeLists.txt b/extras/CMakeLists.txt
index 88668df0b..4cda43992 100644
--- a/extras/CMakeLists.txt
+++ b/extras/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
project(extras)
list(APPEND CMAKE_MODULE_PATH
diff --git a/extras/libmemif/CMakeLists.txt b/extras/libmemif/CMakeLists.txt
index 3cb3a9875..e407078e4 100644
--- a/extras/libmemif/CMakeLists.txt
+++ b/extras/libmemif/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
project(libmemif)
list(APPEND MODULE_PATH
diff --git a/extras/libyang/CMakeLists.txt b/extras/libyang/CMakeLists.txt
index 70218f643..1956d185a 100644
--- a/extras/libyang/CMakeLists.txt
+++ b/extras/libyang/CMakeLists.txt
@@ -10,7 +10,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
project(libyang)
list(APPEND MODULE_PATH
diff --git a/extras/router-plugin/CMakeLists.txt b/extras/router-plugin/CMakeLists.txt
index bbff755d4..81ad2e628 100644
--- a/extras/router-plugin/CMakeLists.txt
+++ b/extras/router-plugin/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(router-plugin)
include(GNUInstallDirs)
diff --git a/extras/sysrepo/CMakeLists.txt b/extras/sysrepo/CMakeLists.txt
index c4b74e07b..edf78105a 100644
--- a/extras/sysrepo/CMakeLists.txt
+++ b/extras/sysrepo/CMakeLists.txt
@@ -10,7 +10,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
project(sysrepo)
list(APPEND MODULE_PATH
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index c9a536dd6..64b93d997 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(hicn-light)
@@ -42,7 +42,10 @@ endif ()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
message("############ Detected cross compile for $ENV{CMAKE_SYSTEM_NAME}")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS}")
+ # Android uses static libs, so we need to link all the dependencies to the executable
+ find_package(OpenSSL REQUIRED)
+ find_package(LibEvent REQUIRED)
+ set(ANDROID_LIBRARIES ${LIBEVENT_LIBRARIES} ${OPENSSL_LIBRARIES})
endif()
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DLIBRTA_DISABLE_VALIDATION -DPARCLibrary_DISABLE_VALIDATION")
@@ -50,14 +53,14 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DLIBRTA_DISABLE_VALIDATION
include(IosMacros)
include(WindowsMacros)
-find_package_wrapper(Libparc REQUIRED)
+find_package(Libparc REQUIRED)
set(HICN_LIGHT hicn-light CACHE INTERNAL "" FORCE)
set(HICN_LIGHT_CONTROL ${HICN_LIGHT}-control CACHE INTERNAL "" FORCE)
set(HICN_LIGHT_DAEMON ${HICN_LIGHT}-daemon CACHE INTERNAL "" FORCE)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package_wrapper(Libhicn REQUIRED)
+ find_package(Libhicn REQUIRED)
else()
if (DISABLE_SHARED_LIBRARIES)
if (WIN32)
@@ -83,12 +86,12 @@ find_package(Threads REQUIRED)
set(LIBHICN_LIGHT hicn-light)
set(LIBHICN_LIGHT_STATIC ${LIBHICN_LIGHT}.static)
-set(HICN_LIGHT_LINK_LIBRARIES
- ${LIBHICN_LIGHT_STATIC}
- ${HICN_LIBRARIES}
+set(LIBRARIES
${LIBPARC_LIBRARIES}
+ ${HICN_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${WINDOWS_LIBRARIES}
+ ${ANDROID_LIBRARIES}
)
set(HICN_LIGHT_LIBRARIES_LIST "${LIBPARC_LIBRARIES};${CMAKE_THREAD_LIBS_INIT};${WINDOWS_LIBRARIES}" CACHE INTERNAL "HICN_LIGHT_LIBRARIES_LIST")
@@ -102,7 +105,7 @@ list(APPEND HICN_LIGHT_INCLUDE_DIRS
)
if (UNIX)
- list(APPEND HICN_LIGHT_LINK_LIBRARIES
+ list(APPEND LIBRARIES
m
)
endif()
diff --git a/hicn-light/src/hicn/command_line/controller/CMakeLists.txt b/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
index 68caa7dc8..4cbd49220 100644
--- a/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
+++ b/hicn-light/src/hicn/command_line/controller/CMakeLists.txt
@@ -20,11 +20,16 @@ if (WIN32)
endif()
if (NOT DISABLE_EXECUTABLES)
+ if (${CMAKE_SYSTEM_NAME} MATCHES Android)
+ set(LINK_FLAGS "-Wl,--unresolved-symbols=ignore-in-object-files")
+ endif()
+
build_executable(${HICN_LIGHT_CONTROL}
SOURCES ${CONTROLLER_SRC}
- LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_STATIC}
DEPENDS ${LIBHICN_LIGHT_STATIC}
COMPONENT ${HICN_LIGHT}
DEFINITIONS ${COMPILER_DEFINITIONS}
+ LINK_FLAGS ${LINK_FLAGS}
)
endif ()
diff --git a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt b/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
index ce62b51e2..a86826f09 100644
--- a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
+++ b/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
@@ -14,14 +14,15 @@
list(APPEND DAEMON_SRC
hicnLightDaemon_main.c
)
+
if (WIN32)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" )
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"")
endif()
-if (NOT DISABLE_EXECUTABLES)
+if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Android")
build_executable(${HICN_LIGHT_DAEMON}
SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_STATIC}
DEPENDS ${LIBHICN_LIGHT_STATIC}
COMPONENT ${HICN_LIGHT}
DEFINITIONS ${COMPILER_DEFINITIONS}
diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt
index 45f36e8ff..104026355 100644
--- a/hicn-light/src/hicn/config/CMakeLists.txt
+++ b/hicn-light/src/hicn/config/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/commandOps.h
${CMAKE_CURRENT_SOURCE_DIR}/commandParser.h
diff --git a/hicn-light/src/hicn/config/commandOps.c b/hicn-light/src/hicn/config/commandOps.c
index b00e48e2a..dd8e148d0 100644
--- a/hicn-light/src/hicn/config/commandOps.c
+++ b/hicn-light/src/hicn/config/commandOps.c
@@ -13,7 +13,6 @@
* limitations under the License.
*/
-
#include <hicn/hicn-light/config.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/hicn-light/src/hicn/content_store/CMakeLists.txt b/hicn-light/src/hicn/content_store/CMakeLists.txt
index 85643cf5e..aaf256118 100644
--- a/hicn-light/src/hicn/content_store/CMakeLists.txt
+++ b/hicn-light/src/hicn/content_store/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/contentStoreEntry.h
${CMAKE_CURRENT_SOURCE_DIR}/contentStoreInterface.h
diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt
index 5e2b696d7..1b13be91f 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/connectionManager.h
${CMAKE_CURRENT_SOURCE_DIR}/connectionState.h
diff --git a/hicn-light/src/hicn/io/CMakeLists.txt b/hicn-light/src/hicn/io/CMakeLists.txt
index eb69485a5..cc4f7371f 100644
--- a/hicn-light/src/hicn/io/CMakeLists.txt
+++ b/hicn-light/src/hicn/io/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/addressPair.h
${CMAKE_CURRENT_SOURCE_DIR}/ioOperations.h
diff --git a/hicn-light/src/hicn/messenger/CMakeLists.txt b/hicn-light/src/hicn/messenger/CMakeLists.txt
index 92bc13b5b..69a6c32d1 100644
--- a/hicn-light/src/hicn/messenger/CMakeLists.txt
+++ b/hicn-light/src/hicn/messenger/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/missiveDeque.h
${CMAKE_CURRENT_SOURCE_DIR}/missive.h
diff --git a/hicn-light/src/hicn/platforms/CMakeLists.txt b/hicn-light/src/hicn/platforms/CMakeLists.txt
index 191a72213..4073e0558 100644
--- a/hicn-light/src/hicn/platforms/CMakeLists.txt
+++ b/hicn-light/src/hicn/platforms/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/android/system.c
diff --git a/hicn-light/src/hicn/processor/CMakeLists.txt b/hicn-light/src/hicn/processor/CMakeLists.txt
index b7eeabe3b..17c3b1f88 100644
--- a/hicn-light/src/hicn/processor/CMakeLists.txt
+++ b/hicn-light/src/hicn/processor/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/fibEntry.h
${CMAKE_CURRENT_SOURCE_DIR}/fibEntryList.h
diff --git a/hicn-light/src/hicn/socket/CMakeLists.txt b/hicn-light/src/hicn/socket/CMakeLists.txt
index 775693bf0..8c8a757fb 100644
--- a/hicn-light/src/hicn/socket/CMakeLists.txt
+++ b/hicn-light/src/hicn/socket/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
if (UNIX AND NOT APPLE)
list(APPEND HEADER_FILES
socket/api.h
diff --git a/hicn-light/src/hicn/strategies/CMakeLists.txt b/hicn-light/src/hicn/strategies/CMakeLists.txt
index 400efcde9..886aa137c 100644
--- a/hicn-light/src/hicn/strategies/CMakeLists.txt
+++ b/hicn-light/src/hicn/strategies/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/strategyImpl.h
${CMAKE_CURRENT_SOURCE_DIR}/loadBalancer.h
diff --git a/hicn-light/src/hicn/utils/CMakeLists.txt b/hicn-light/src/hicn/utils/CMakeLists.txt
index 1ab38deba..c8c9b8487 100644
--- a/hicn-light/src/hicn/utils/CMakeLists.txt
+++ b/hicn-light/src/hicn/utils/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/address.h
${CMAKE_CURRENT_SOURCE_DIR}/addressList.h
diff --git a/hicn-plugin/.clang-format b/hicn-plugin/.clang-format
index 8b5c955ce..351a70e20 100644
--- a/hicn-plugin/.clang-format
+++ b/hicn-plugin/.clang-format
@@ -18,4 +18,3 @@ ForEachMacros:
- 'vec_foreach_index'
- 'vec_foreach_index_backwards'
- 'vlib_foreach_rx_tx'
-
diff --git a/hicn-plugin/CMakeLists.txt b/hicn-plugin/CMakeLists.txt
index ea933d8a0..9f5553857 100644
--- a/hicn-plugin/CMakeLists.txt
+++ b/hicn-plugin/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(hicn-plugin)
diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt
index d81ed22b7..c90ae80a2 100644
--- a/hicn-plugin/src/CMakeLists.txt
+++ b/hicn-plugin/src/CMakeLists.txt
@@ -11,13 +11,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
# Dependencies
-
find_package(Vpp REQUIRED)
-include_directories(${VPP_INCLUDE_DIR})
+include_directories(${HICN_INCLUDE_DIRS} ${VPP_INCLUDE_DIR})
set(LIBHICN_FILES
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/mapme.c
diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c
index 81a97c604..8ecbf7a95 100644
--- a/hicn-plugin/src/cli.c
+++ b/hicn-plugin/src/cli.c
@@ -65,8 +65,8 @@ hicn_cli_node_ctl_start_set_command_fn (vlib_main_t *vm,
get_error_string (ret));
return (ret == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, get_error_string (ret));
+ 0 :
+ clib_error_return (0, get_error_string (ret));
}
/*
@@ -103,8 +103,8 @@ hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t *vm,
node_ctl_params.pit_max_lifetime_sec, node_ctl_params.cs_max_size, ~0);
return (ret == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, get_error_string (ret));
+ 0 :
+ clib_error_return (0, get_error_string (ret));
}
#define DFLTD_RANGE_OK(val, min, max) \
@@ -201,8 +201,8 @@ hicn_cli_node_ctl_param_set_command_fn (vlib_main_t *vm,
"compilation time for better performances\n");
return (rv == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, "%s '%U'", get_error_string (rv),
+ 0 :
+ clib_error_return (0, "%s '%U'", get_error_string (rv),
format_unformat_error, line_input);
}
@@ -348,8 +348,8 @@ done:
hicn_main.pitcs.pcs_table->ht_overflow_buckets_used);
}
return (ret == HICN_ERROR_NONE) ?
- 0 :
- clib_error_return (0, "%s\n", get_error_string (ret));
+ 0 :
+ clib_error_return (0, "%s\n", get_error_string (ret));
}
/*
@@ -408,8 +408,8 @@ hicn_cli_strategy_set_command_fn (vlib_main_t *vm,
rv = hicn_route_set_strategy (&prefix, strategy_id);
cl_err = (rv == HICN_ERROR_NONE) ?
- NULL :
- clib_error_return (0, get_error_string (rv));
+ NULL :
+ clib_error_return (0, get_error_string (rv));
done:
return (cl_err);
@@ -731,8 +731,8 @@ hicn_enable_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
done:
cl_err = (rv == HICN_ERROR_NONE) ?
- NULL :
- clib_error_return (0, get_error_string (rv));
+ NULL :
+ clib_error_return (0, get_error_string (rv));
return cl_err;
}
@@ -776,8 +776,8 @@ hicn_disable_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
done:
cl_err = (rv == HICN_ERROR_NONE) ?
- NULL :
- clib_error_return (0, get_error_string (rv));
+ NULL :
+ clib_error_return (0, get_error_string (rv));
return cl_err;
}
diff --git a/hicn-plugin/vapi/CMakeLists.txt b/hicn-plugin/vapi/CMakeLists.txt
index 9464cd944..6c176b9f3 100644
--- a/hicn-plugin/vapi/CMakeLists.txt
+++ b/hicn-plugin/vapi/CMakeLists.txt
@@ -10,7 +10,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
set(SAFE_VAPI safe_vapi CACHE INTERNAL "" FORCE)
set(SAFE_VAPI_SHARED ${SAFE_VAPI}.shared CACHE INTERNAL "" FORCE)
diff --git a/lib/.clang-format b/lib/.clang-format
index 8b5c955ce..351a70e20 100644
--- a/lib/.clang-format
+++ b/lib/.clang-format
@@ -18,4 +18,3 @@ ForEachMacros:
- 'vec_foreach_index'
- 'vec_foreach_index_backwards'
- 'vlib_foreach_rx_tx'
-
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 0512b7c64..65c1cd4ee 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required (VERSION 3.10 FATAL_ERROR)
project(libhicn C)
#include(CTest)
diff --git a/lib/includes/hicn/compat.h b/lib/includes/hicn/compat.h
index 35b6e6fc5..486c82348 100644
--- a/lib/includes/hicn/compat.h
+++ b/lib/includes/hicn/compat.h
@@ -454,7 +454,10 @@ int hicn_data_get_payload_type (const hicn_header_t *data,
int hicn_data_set_payload_type (hicn_header_t *data,
hicn_payload_type_t payload_type);
int hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet);
-
+int hicn_packet_get_signature_gap (hicn_format_t format,
+ const hicn_header_t *h, uint8_t *bytes);
+int hicn_packet_set_signature_gap (hicn_format_t format, hicn_header_t *h,
+ uint8_t bytes);
#endif /* HICN_COMPAT_H */
/*
diff --git a/lib/includes/hicn/ops.h b/lib/includes/hicn/ops.h
index 7d4ae86d8..e5b1c088c 100644
--- a/lib/includes/hicn/ops.h
+++ b/lib/includes/hicn/ops.h
@@ -30,8 +30,8 @@
/*
* hICN operations on packets
*
- * All prototypes take an hicn_type_t parameter as their first argument, as this
- * decides the sequence of protocols that are being used by the different
+ * All prototypes take an hicn_type_t parameter as their first argument, as
+ * this decides the sequence of protocols that are being used by the different
* operations.
*/
@@ -42,7 +42,7 @@ typedef struct hicn_ops_s
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the packet
*/
- int (*init_packet_header) (hicn_type_t type, hicn_protocol_t * h);
+ int (*init_packet_header) (hicn_type_t type, hicn_protocol_t *h);
/**
* @brief Retrieves an Interest locator
@@ -51,8 +51,8 @@ typedef struct hicn_ops_s
* @param [out] ip_address - Retrieved locator
* @return hICN error code
*/
- int (*get_interest_locator) (hicn_type_t type, const hicn_protocol_t * h,
- ip46_address_t * ip_address);
+ int (*get_interest_locator) (hicn_type_t type, const hicn_protocol_t *h,
+ ip46_address_t *ip_address);
/**
* @brief Sets an Interest locator
@@ -61,8 +61,8 @@ typedef struct hicn_ops_s
* @param [in] ip_address - Locator to set
* @return hICN error code
*/
- int (*set_interest_locator) (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * ip_address);
+ int (*set_interest_locator) (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *ip_address);
/**
* @brief Retrieves an Interest name
@@ -71,8 +71,8 @@ typedef struct hicn_ops_s
* @param [out] name - Retrieved name
* @return hICN error code
*/
- int (*get_interest_name) (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_t * name);
+ int (*get_interest_name) (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name);
/**
* @brief Sets an Interest name
@@ -81,8 +81,8 @@ typedef struct hicn_ops_s
* @param [in] name - Name to set
* @return hICN error code
*/
- int (*set_interest_name) (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_t * name);
+ int (*set_interest_name) (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name);
/**
* @brief Retrieves an Interest name suffix
@@ -91,9 +91,8 @@ typedef struct hicn_ops_s
* @param [out] suffix - Retrieved name suffix
* @return hICN error code
*/
- int (*get_interest_name_suffix) (hicn_type_t type,
- const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix);
+ int (*get_interest_name_suffix) (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix);
/**
* @brief Sets an Interest name suffix
@@ -102,8 +101,8 @@ typedef struct hicn_ops_s
* @param [in] suffix - Name suffix to set
* @return hICN error code
*/
- int (*set_interest_name_suffix) (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix);
+ int (*set_interest_name_suffix) (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix);
/**
* @brief Set flag to mark current packet as interest
@@ -111,7 +110,7 @@ typedef struct hicn_ops_s
* @param [in,out] h - Buffer holding the Interest packet
* @return hICN error code
*/
- int (*mark_packet_as_interest) (hicn_type_t type, hicn_protocol_t * h);
+ int (*mark_packet_as_interest) (hicn_type_t type, hicn_protocol_t *h);
/**
* @brief Set flag to mark current packet as data
@@ -119,7 +118,7 @@ typedef struct hicn_ops_s
* @param [in,out] h - Buffer holding the Interest packet
* @return hICN error code
*/
- int (*mark_packet_as_data) (hicn_type_t type, hicn_protocol_t * h);
+ int (*mark_packet_as_data) (hicn_type_t type, hicn_protocol_t *h);
/**
* @brief Clear the necessary Interest fields in order to hash it
@@ -127,7 +126,7 @@ typedef struct hicn_ops_s
* @param [in,out] h - Buffer holding the Interest packet
* @return hICN error code
*/
- int (*reset_interest_for_hash) (hicn_type_t type, hicn_protocol_t * h);
+ int (*reset_interest_for_hash) (hicn_type_t type, hicn_protocol_t *h);
/**
* @brief Retrieves a Data locator
@@ -136,8 +135,8 @@ typedef struct hicn_ops_s
* @param [out] ip_address - Retrieved locator
* @return hICN error code
*/
- int (*get_data_locator) (hicn_type_t type, const hicn_protocol_t * h,
- ip46_address_t * ip_address);
+ int (*get_data_locator) (hicn_type_t type, const hicn_protocol_t *h,
+ ip46_address_t *ip_address);
/**
* @brief Sets a Data locator
@@ -146,8 +145,8 @@ typedef struct hicn_ops_s
* @param [in] ip_address - Locator to set
* @return hICN error code
*/
- int (*set_data_locator) (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * ip_address);
+ int (*set_data_locator) (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *ip_address);
/**
* @brief Retrieves a Data name
@@ -156,8 +155,8 @@ typedef struct hicn_ops_s
* @param [out] name - Retrieved name
* @return hICN error code
*/
- int (*get_data_name) (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_t * name);
+ int (*get_data_name) (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name);
/**
* @brief Sets a Data name
@@ -166,8 +165,8 @@ typedef struct hicn_ops_s
* @param [in] name - Name to set
* @return hICN error code
*/
- int (*set_data_name) (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_t * name);
+ int (*set_data_name) (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name);
/**
* @brief Retrieves a Data name suffix
@@ -176,8 +175,8 @@ typedef struct hicn_ops_s
* @param [out] suffix - Retrieved name suffix
* @return hICN error code
*/
- int (*get_data_name_suffix) (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix);
+ int (*get_data_name_suffix) (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix);
/**
* @brief Sets a Data name suffix
@@ -186,8 +185,8 @@ typedef struct hicn_ops_s
* @param [in] suffix - Name suffix to set
* @return hICN error code
*/
- int (*set_data_name_suffix) (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix);
+ int (*set_data_name_suffix) (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix);
/**
* @brief Retrieves a Data pathlabel
@@ -196,8 +195,8 @@ typedef struct hicn_ops_s
* @param [out] pathlabel - Retrieved pathlabel
* @return hICN error code
*/
- int (*get_data_pathlabel) (hicn_type_t type, const hicn_protocol_t * h,
- u32 * pathlabel);
+ int (*get_data_pathlabel) (hicn_type_t type, const hicn_protocol_t *h,
+ u32 *pathlabel);
/**
* @brief Sets a Data pathlabel
@@ -206,7 +205,7 @@ typedef struct hicn_ops_s
* @param [in] pathlabel - Pathlabel to set
* @return hICN error code
*/
- int (*set_data_pathlabel) (hicn_type_t type, hicn_protocol_t * h,
+ int (*set_data_pathlabel) (hicn_type_t type, hicn_protocol_t *h,
const u32 pathlabel);
/**
@@ -216,7 +215,7 @@ typedef struct hicn_ops_s
* @param [in] pathlabel - Face identifier used to update pathlabel
* @return hICN error code
*/
- int (*update_data_pathlabel) (hicn_type_t type, hicn_protocol_t * h,
+ int (*update_data_pathlabel) (hicn_type_t type, hicn_protocol_t *h,
const hicn_faceid_t face_id);
/**
@@ -225,7 +224,7 @@ typedef struct hicn_ops_s
* @param [in,out] h - Buffer holding the Data packet
* @return hICN error code
*/
- int (*reset_data_for_hash) (hicn_type_t type, hicn_protocol_t * h);
+ int (*reset_data_for_hash) (hicn_type_t type, hicn_protocol_t *h);
/**
* @brief Retrieves an Interest or Data lifetime
@@ -234,8 +233,8 @@ typedef struct hicn_ops_s
* @param [out] pathlabel - Retrieved lifetime
* @return hICN error code
*/
- int (*get_lifetime) (hicn_type_t type, const hicn_protocol_t * h,
- hicn_lifetime_t * lifetime);
+ int (*get_lifetime) (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_lifetime_t *lifetime);
/**
* @brief Sets an Interest or Data lifetime
@@ -244,7 +243,7 @@ typedef struct hicn_ops_s
* @param [in] pathlabel - Lifetime to set
* @return hICN error code
*/
- int (*set_lifetime) (hicn_type_t type, hicn_protocol_t * h,
+ int (*set_lifetime) (hicn_type_t type, hicn_protocol_t *h,
const hicn_lifetime_t lifetime);
/**
@@ -257,19 +256,20 @@ typedef struct hicn_ops_s
* and used internally to carry payload length across protocol headers)
* @return hICN error code
*/
- int (*update_checksums) (hicn_type_t type, hicn_protocol_t * h,
+ int (*update_checksums) (hicn_type_t type, hicn_protocol_t *h,
u16 partial_csum, size_t payload_length);
/**
* @brief Validate all checksums in packet headers
* @param [in] type - hICN packet type
* @param [in] h - Buffer holding the packet
- * @param [in] partial_csum - Partial checksum, or zero if no partial checksum available
+ * @param [in] partial_csum - Partial checksum, or zero if no partial
+ * checksum available
* @param [in] payload_length - Payload length (can be set to ~0, retrieved
* and used internally to carry payload length across protocol headers)
* @return hICN error code
*/
- int (*verify_checksums) (hicn_type_t type, hicn_protocol_t * h,
+ int (*verify_checksums) (hicn_type_t type, hicn_protocol_t *h,
u16 partial_csum, size_t payload_length);
/**
@@ -281,9 +281,9 @@ typedef struct hicn_ops_s
* compute incremental checksums)
* @return hICN error code
*/
- int (*rewrite_interest) (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new,
- ip46_address_t * addr_old);
+ int (*rewrite_interest) (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new,
+ ip46_address_t *addr_old);
/**
* @brief Rewrite a Data packet header (locator + pathlabel)
@@ -297,11 +297,10 @@ typedef struct hicn_ops_s
* before update it
* @return hICN error code
*/
- int (*rewrite_data) (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new,
- ip46_address_t * addr_old,
- const hicn_faceid_t face_id,
- u8 reset_pl);
+ int (*rewrite_data) (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new,
+ ip46_address_t *addr_old, const hicn_faceid_t face_id,
+ u8 reset_pl);
/**
* @brief Return the packet length
@@ -310,8 +309,8 @@ typedef struct hicn_ops_s
* @parma [out] length - Returned packet length
* @return hICN error code
*/
- int (*get_length) (hicn_type_t type, const hicn_protocol_t * h,
- size_t * length);
+ int (*get_length) (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *length);
/**
* @brief Return the current packet header length
@@ -320,9 +319,8 @@ typedef struct hicn_ops_s
* @parma [out] header_length - Returned packet current header length
* @return hICN error code
*/
- int (*get_current_header_length) (hicn_type_t type,
- const hicn_protocol_t * h,
- size_t * header_length);
+ int (*get_current_header_length) (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length);
/**
* @brief Return the packet header length
@@ -331,8 +329,8 @@ typedef struct hicn_ops_s
* @parma [out] header_length - Returned packet header length
* @return hICN error code
*/
- int (*get_header_length) (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length);
+ int (*get_header_length) (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length);
/**
* @brief Return the packet payload length
@@ -341,8 +339,8 @@ typedef struct hicn_ops_s
* @parma [out] payload_length - Returned packet payload length
* @return hICN error code
*/
- int (*get_payload_length) (hicn_type_t type, const hicn_protocol_t * h,
- size_t * payload_length);
+ int (*get_payload_length) (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *payload_length);
/**
* @brief Sets the packet paylaod length
@@ -351,7 +349,7 @@ typedef struct hicn_ops_s
* @parma [out] payload_length - Payload length to set
* @return hICN error code
*/
- int (*set_payload_length) (hicn_type_t type, hicn_protocol_t * h,
+ int (*set_payload_length) (hicn_type_t type, hicn_protocol_t *h,
size_t payload_length);
/**
@@ -361,8 +359,8 @@ typedef struct hicn_ops_s
* @param [out] signature_size - Retrieved signature size
* @return hICN error code
*/
- int (*get_signature_size) (hicn_type_t type, const hicn_protocol_t * h,
- size_t * signature_size);
+ int (*get_signature_size) (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size);
/**
* @brief Sets an Interest or Data signature size
@@ -371,18 +369,41 @@ typedef struct hicn_ops_s
* @param [in] signature_size - Signature size to set
* @return hICN error code
*/
- int (*set_signature_size) (hicn_type_t type, hicn_protocol_t * h,
+ int (*set_signature_size) (hicn_type_t type, hicn_protocol_t *h,
size_t signature_size);
/**
+ * @brief Sets an Interest or Data signature gap between maximum size and
+ * real size
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] signature_size - Signature size to set
+ * @return hICN error code
+ */
+ int (*set_signature_gap) (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t signature_gap);
+
+ /**
+ * @brief gets an Interest or Data signature gap between maximum size and
+ * real size
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest or Data packet
+ * @param [in] signature_size - retrieve the gap between maximum size and
+ * real size
+ * @return hICN error code
+ */
+ int (*get_signature_gap) (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *signature_gap);
+
+ /**
* @brief Gets the signature timestamp
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the Interest or Data packet
* @param [out] signature_timestamp - Retrieved signature timestamp
* @return hICN error code
*/
- int (*get_signature_timestamp) (hicn_type_t type, const hicn_protocol_t * h,
- uint64_t *signature_timestamp);
+ int (*get_signature_timestamp) (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp);
/**
* @brief Sets the signature timestamp
@@ -391,9 +412,8 @@ typedef struct hicn_ops_s
* @param [in] signature_timestamp - Signature timestamp to set
* @return hICN error code
*/
- int (*set_signature_timestamp) (hicn_type_t type, hicn_protocol_t * h,
- uint64_t signature_timestamp);
-
+ int (*set_signature_timestamp) (hicn_type_t type, hicn_protocol_t *h,
+ uint64_t signature_timestamp);
/**
* @brief Gets the signature validation algorithm
@@ -402,8 +422,8 @@ typedef struct hicn_ops_s
* @param [out] validation_algorithm - Retrieved validation_algorithm
* @return hICN error code
*/
- int (*get_validation_algorithm) (hicn_type_t type, const hicn_protocol_t * h,
- uint8_t *validation_algorithm);
+ int (*get_validation_algorithm) (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm);
/**
* @brief Sets the signature validation algorithm
@@ -412,9 +432,8 @@ typedef struct hicn_ops_s
* @param [in] validation_algorithm - Validation algorithm enumeration
* @return hICN error code
*/
- int (*set_validation_algorithm) (hicn_type_t type, hicn_protocol_t * h,
- uint8_t validation_algorithm);
-
+ int (*set_validation_algorithm) (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t validation_algorithm);
/**
* @brief Gets the key id
@@ -423,8 +442,8 @@ typedef struct hicn_ops_s
* @param [out] key_id - Retrieved key id first byte address
* @return hICN error code
*/
- int (*get_key_id) (hicn_type_t type, hicn_protocol_t * h,
- uint8_t **key_id, uint8_t *key_id_size);
+ int (*get_key_id) (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size);
/**
* @brief Sets the key id
@@ -433,62 +452,69 @@ typedef struct hicn_ops_s
* @param [in] key_id - Key id first byte address
* @return hICN error code
*/
- int (*set_key_id) (hicn_type_t type, hicn_protocol_t * h,
- uint8_t *key_id);
+ int (*set_key_id) (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id);
- /**
+ /**
* @brief Get a pointer to the signature field in the packet
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the Interest or Data packet
- * @param [out] signature - Pointer to the memory region holding the signature
+ * @param [out] signature - Pointer to the memory region holding the
+ * signature
* @return hICN error code
*/
- int (*get_signature) (hicn_type_t type, hicn_protocol_t * h,
- uint8_t ** signature);
+ int (*get_signature) (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t **signature);
} hicn_ops_t;
-#define DECLARE_HICN_OPS(protocol) \
- const hicn_ops_t hicn_ops_ ## protocol = { \
- ATTR_INIT(init_packet_header, protocol ## _init_packet_header), \
- ATTR_INIT(get_interest_locator, protocol ## _get_interest_locator), \
- ATTR_INIT(set_interest_locator, protocol ## _set_interest_locator), \
- ATTR_INIT(get_interest_name, protocol ## _get_interest_name), \
- ATTR_INIT(set_interest_name, protocol ## _set_interest_name), \
- ATTR_INIT(get_interest_name_suffix, protocol ## _get_interest_name_suffix), \
- ATTR_INIT(set_interest_name_suffix, protocol ## _set_interest_name_suffix), \
- ATTR_INIT(mark_packet_as_interest, protocol ## _mark_packet_as_interest), \
- ATTR_INIT(mark_packet_as_data, protocol ## _mark_packet_as_data), \
- ATTR_INIT(reset_interest_for_hash, protocol ## _reset_interest_for_hash), \
- ATTR_INIT(get_data_locator, protocol ## _get_data_locator), \
- ATTR_INIT(set_data_locator, protocol ## _set_data_locator), \
- ATTR_INIT(get_data_name, protocol ## _get_data_name), \
- ATTR_INIT(set_data_name, protocol ## _set_data_name), \
- ATTR_INIT(get_data_name_suffix, protocol ## _get_data_name_suffix), \
- ATTR_INIT(set_data_name_suffix, protocol ## _set_data_name_suffix), \
- ATTR_INIT(get_data_pathlabel, protocol ## _get_data_pathlabel), \
- ATTR_INIT(set_data_pathlabel, protocol ## _set_data_pathlabel), \
- ATTR_INIT(update_data_pathlabel, protocol ## _update_data_pathlabel), \
- ATTR_INIT(reset_data_for_hash, protocol ## _reset_data_for_hash), \
- ATTR_INIT(get_lifetime, protocol ## _get_lifetime), \
- ATTR_INIT(set_lifetime, protocol ## _set_lifetime), \
- ATTR_INIT(update_checksums, protocol ## _update_checksums), \
- ATTR_INIT(verify_checksums, protocol ## _verify_checksums), \
- ATTR_INIT(rewrite_interest, protocol ## _rewrite_interest), \
- ATTR_INIT(rewrite_data, protocol ## _rewrite_data), \
- ATTR_INIT(get_length, protocol ## _get_length), \
- ATTR_INIT(get_current_header_length,protocol ## _get_current_header_length),\
- ATTR_INIT(get_header_length, protocol ## _get_header_length), \
- ATTR_INIT(get_payload_length, protocol ## _get_payload_length), \
- ATTR_INIT(set_payload_length, protocol ## _set_payload_length), \
- ATTR_INIT(get_signature_size, protocol ## _get_signature_size), \
- ATTR_INIT(set_signature_size, protocol ## _set_signature_size), \
- ATTR_INIT(get_signature_timestamp, protocol ## _get_signature_timestamp), \
- ATTR_INIT(set_signature_timestamp, protocol ## _set_signature_timestamp), \
- ATTR_INIT(get_validation_algorithm, protocol ## _get_validation_algorithm), \
- ATTR_INIT(set_validation_algorithm, protocol ## _set_validation_algorithm), \
- ATTR_INIT(get_key_id, protocol ## _get_key_id), \
- ATTR_INIT(set_key_id, protocol ## _set_key_id), \
- ATTR_INIT(get_signature, protocol ## _get_signature), \
+#define DECLARE_HICN_OPS(protocol) \
+ const hicn_ops_t hicn_ops_##protocol = { \
+ ATTR_INIT (init_packet_header, protocol##_init_packet_header), \
+ ATTR_INIT (get_interest_locator, protocol##_get_interest_locator), \
+ ATTR_INIT (set_interest_locator, protocol##_set_interest_locator), \
+ ATTR_INIT (get_interest_name, protocol##_get_interest_name), \
+ ATTR_INIT (set_interest_name, protocol##_set_interest_name), \
+ ATTR_INIT (get_interest_name_suffix, \
+ protocol##_get_interest_name_suffix), \
+ ATTR_INIT (set_interest_name_suffix, \
+ protocol##_set_interest_name_suffix), \
+ ATTR_INIT (mark_packet_as_interest, protocol##_mark_packet_as_interest), \
+ ATTR_INIT (mark_packet_as_data, protocol##_mark_packet_as_data), \
+ ATTR_INIT (reset_interest_for_hash, protocol##_reset_interest_for_hash), \
+ ATTR_INIT (get_data_locator, protocol##_get_data_locator), \
+ ATTR_INIT (set_data_locator, protocol##_set_data_locator), \
+ ATTR_INIT (get_data_name, protocol##_get_data_name), \
+ ATTR_INIT (set_data_name, protocol##_set_data_name), \
+ ATTR_INIT (get_data_name_suffix, protocol##_get_data_name_suffix), \
+ ATTR_INIT (set_data_name_suffix, protocol##_set_data_name_suffix), \
+ ATTR_INIT (get_data_pathlabel, protocol##_get_data_pathlabel), \
+ ATTR_INIT (set_data_pathlabel, protocol##_set_data_pathlabel), \
+ ATTR_INIT (update_data_pathlabel, protocol##_update_data_pathlabel), \
+ ATTR_INIT (reset_data_for_hash, protocol##_reset_data_for_hash), \
+ ATTR_INIT (get_lifetime, protocol##_get_lifetime), \
+ ATTR_INIT (set_lifetime, protocol##_set_lifetime), \
+ ATTR_INIT (update_checksums, protocol##_update_checksums), \
+ ATTR_INIT (verify_checksums, protocol##_verify_checksums), \
+ ATTR_INIT (rewrite_interest, protocol##_rewrite_interest), \
+ ATTR_INIT (rewrite_data, protocol##_rewrite_data), \
+ ATTR_INIT (get_length, protocol##_get_length), \
+ ATTR_INIT (get_current_header_length, \
+ protocol##_get_current_header_length), \
+ ATTR_INIT (get_header_length, protocol##_get_header_length), \
+ ATTR_INIT (get_payload_length, protocol##_get_payload_length), \
+ ATTR_INIT (set_payload_length, protocol##_set_payload_length), \
+ ATTR_INIT (get_signature_size, protocol##_get_signature_size), \
+ ATTR_INIT (get_signature_timestamp, protocol##_get_signature_timestamp), \
+ ATTR_INIT (set_signature_timestamp, protocol##_set_signature_timestamp), \
+ ATTR_INIT (get_validation_algorithm, \
+ protocol##_get_validation_algorithm), \
+ ATTR_INIT (set_validation_algorithm, \
+ protocol##_set_validation_algorithm), \
+ ATTR_INIT (get_key_id, protocol##_get_key_id), \
+ ATTR_INIT (set_key_id, protocol##_set_key_id), \
+ ATTR_INIT (get_signature, protocol##_get_signature), \
+ ATTR_INIT (set_signature_gap, protocol##_set_signature_gap), \
+ ATTR_INIT (set_signature_size, protocol##_set_signature_size), \
+ ATTR_INIT (get_signature_gap, protocol##_get_signature_gap), \
}
/**
@@ -500,13 +526,14 @@ extern const hicn_ops_t *const hicn_ops_vft[];
/*
* Helpers for writing recursive protocol operations on packet headers
*
- * NOTE : we cannot use a shift operation as IPPROTO_NONE != 0 (and 0 is IPv4...)
+ * NOTE : we cannot use a shift operation as IPPROTO_NONE != 0 (and 0 is
+ * IPv4...)
*/
always_inline hicn_type_t
TYPE_POP (hicn_type_t type)
{
#ifndef _WIN32
- return HICN_TYPE(type.l2, type.l3, type.l4, IPPROTO_NONE);
+ return HICN_TYPE (type.l2, type.l3, type.l4, IPPROTO_NONE);
#else
hicn_type_t new_type;
new_type.l1 = type.l2;
@@ -518,17 +545,19 @@ TYPE_POP (hicn_type_t type)
}
always_inline hicn_protocol_t *
-PAYLOAD (hicn_type_t type, const hicn_protocol_t * h)
+PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
{
size_t header_length;
- int rc = hicn_ops_vft[type.l1]->get_current_header_length (type, h,
- &header_length);
+ int rc =
+ hicn_ops_vft[type.l1]->get_current_header_length (type, h, &header_length);
if (rc < 0)
return NULL;
return (hicn_protocol_t *) ((u8 *) h + header_length);
}
-#define CHILD_OPS(f, type, h, ...) (hicn_ops_vft[type.l2]->f(TYPE_POP(type), PAYLOAD(type, h), ## __VA_ARGS__))
+#define CHILD_OPS(f, type, h, ...) \
+ (hicn_ops_vft[type.l2]->f (TYPE_POP (type), PAYLOAD (type, h), \
+ ##__VA_ARGS__))
/** Shortcuts to entry points in VFT */
#define HICN_OPS4 hicn_ops_vft[IPPROTO_IP]
@@ -536,125 +565,300 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t * h)
/* Helpers for simple declarations */
-#define DECLARE_init_packet_header(protocol, error) \
- int protocol ## _init_packet_header(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_init_packet_header(protocol, error) \
+ int protocol##_init_packet_header (hicn_type_t type, hicn_protocol_t *h) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_interest_locator(protocol, error) \
- int protocol ## _get_interest_locator(hicn_type_t type, const hicn_protocol_t * h, ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_interest_locator(protocol, error) \
+ int protocol##_get_interest_locator ( \
+ hicn_type_t type, const hicn_protocol_t *h, ip46_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_interest_locator(protocol, error) \
- int protocol ## _set_interest_locator(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_interest_locator(protocol, error) \
+ int protocol##_set_interest_locator (hicn_type_t type, hicn_protocol_t *h, \
+ const ip46_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_interest_name(protocol, error) \
- int protocol ## _get_interest_name(hicn_type_t type, const hicn_protocol_t * h, hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_interest_name(protocol, error) \
+ int protocol##_get_interest_name ( \
+ hicn_type_t type, const hicn_protocol_t *h, hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_interest_name(protocol, error) \
- int protocol ## _set_interest_name(hicn_type_t type, hicn_protocol_t * h, const hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_interest_name(protocol, error) \
+ int protocol##_set_interest_name (hicn_type_t type, hicn_protocol_t *h, \
+ const hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_interest_name_suffix(protocol, error) \
- int protocol ## _get_interest_name_suffix(hicn_type_t type, const hicn_protocol_t * h, hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_interest_name_suffix(protocol, error) \
+ int protocol##_get_interest_name_suffix ( \
+ hicn_type_t type, const hicn_protocol_t *h, hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_interest_name_suffix(protocol, error) \
- int protocol ## _set_interest_name_suffix(hicn_type_t type, hicn_protocol_t * h, const hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_interest_name_suffix(protocol, error) \
+ int protocol##_set_interest_name_suffix ( \
+ hicn_type_t type, hicn_protocol_t *h, const hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_mark_packet_as_interest(protocol, error) \
- int protocol ## _mark_packet_as_interest(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_mark_packet_as_interest(protocol, error) \
+ int protocol##_mark_packet_as_interest (hicn_type_t type, \
+ hicn_protocol_t *h) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_mark_packet_as_data(protocol, error) \
+ int protocol##_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_mark_packet_as_data(protocol, error) \
- int protocol ## _mark_packet_as_data(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_reset_interest_for_hash(protocol, error) \
+ int protocol##_reset_interest_for_hash (hicn_type_t type, \
+ hicn_protocol_t *h) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_reset_interest_for_hash(protocol, error) \
- int protocol ## _reset_interest_for_hash(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_data_locator(protocol, error) \
+ int protocol##_get_data_locator ( \
+ hicn_type_t type, const hicn_protocol_t *h, ip46_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_data_locator(protocol, error) \
+ int protocol##_set_data_locator (hicn_type_t type, hicn_protocol_t *h, \
+ const ip46_address_t *ip_address) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_data_locator(protocol, error) \
- int protocol ## _get_data_locator(hicn_type_t type, const hicn_protocol_t * h, ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_data_name(protocol, error) \
+ int protocol##_get_data_name (hicn_type_t type, const hicn_protocol_t *h, \
+ hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_data_locator(protocol, error) \
- int protocol ## _set_data_locator(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * ip_address) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_data_name(protocol, error) \
+ int protocol##_set_data_name (hicn_type_t type, hicn_protocol_t *h, \
+ const hicn_name_t *name) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_data_name(protocol, error) \
- int protocol ## _get_data_name(hicn_type_t type, const hicn_protocol_t * h, hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_data_name_suffix(protocol, error) \
+ int protocol##_get_data_name_suffix ( \
+ hicn_type_t type, const hicn_protocol_t *h, hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_data_name(protocol, error) \
- int protocol ## _set_data_name(hicn_type_t type, hicn_protocol_t * h, const hicn_name_t * name) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_data_name_suffix(protocol, error) \
+ int protocol##_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, \
+ const hicn_name_suffix_t *suffix) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_data_name_suffix(protocol, error) \
- int protocol ## _get_data_name_suffix(hicn_type_t type, const hicn_protocol_t * h, hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_data_pathlabel(protocol, error) \
+ int protocol##_get_data_pathlabel ( \
+ hicn_type_t type, const hicn_protocol_t *h, u32 *pathlabel) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_data_name_suffix(protocol, error) \
- int protocol ## _set_data_name_suffix(hicn_type_t type, hicn_protocol_t * h, const hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_data_pathlabel(protocol, error) \
+ int protocol##_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, \
+ const u32 pathlabel) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_data_pathlabel(protocol, error) \
- int protocol ## _get_data_pathlabel(hicn_type_t type, const hicn_protocol_t * h, u32 * pathlabel) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_update_data_pathlabel(protocol, error) \
+ int protocol##_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, \
+ const hicn_faceid_t face_id) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_data_pathlabel(protocol, error) \
- int protocol ## _set_data_pathlabel(hicn_type_t type, hicn_protocol_t * h, const u32 pathlabel) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_reset_data_for_hash(protocol, error) \
+ int protocol##_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_update_data_pathlabel(protocol, error) \
- int protocol ## _update_data_pathlabel(hicn_type_t type, hicn_protocol_t * h, const hicn_faceid_t face_id) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_lifetime(protocol, error) \
+ int protocol##_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, \
+ hicn_lifetime_t *lifetime) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_reset_data_for_hash(protocol, error) \
- int protocol ## _reset_data_for_hash(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_lifetime(protocol, error) \
+ int protocol##_set_lifetime (hicn_type_t type, hicn_protocol_t *h, \
+ const hicn_lifetime_t lifetime) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_lifetime(protocol, error) \
- int protocol ## _get_lifetime(hicn_type_t type, const hicn_protocol_t * h, hicn_lifetime_t * lifetime) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_update_checksums(protocol, error) \
+ int protocol##_update_checksums (hicn_type_t type, hicn_protocol_t *h, \
+ u16 partial_csum, size_t payload_length) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_lifetime(protocol, error) \
- int protocol ## _set_lifetime(hicn_type_t type, hicn_protocol_t * h, const hicn_lifetime_t lifetime) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_verify_checksums(protocol, error) \
+ int protocol##_verify_checksums (hicn_type_t type, hicn_protocol_t *h, \
+ u16 partial_csum, size_t payload_length) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_update_checksums(protocol, error) \
- int protocol ## _update_checksums(hicn_type_t type, hicn_protocol_t * h, u16 partial_csum, size_t payload_length) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_rewrite_interest(protocol, error) \
+ int protocol##_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, \
+ const ip46_address_t *addr_new, \
+ ip46_address_t *addr_old) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_verify_checksums(protocol, error) \
- int protocol ## _verify_checksums(hicn_type_t type, hicn_protocol_t * h, u16 partial_csum, size_t payload_length) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_rewrite_data(protocol, error) \
+ int protocol##_rewrite_data ( \
+ hicn_type_t type, hicn_protocol_t *h, const ip46_address_t *addr_new, \
+ ip46_address_t *addr_old, const hicn_faceid_t face_id, u8 reset_pl) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_rewrite_interest(protocol, error) \
- int protocol ## _rewrite_interest(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * addr_new, ip46_address_t * addr_old) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_length(protocol, error) \
+ int protocol##_get_length (hicn_type_t type, const hicn_protocol_t *h, \
+ size_t *length) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_rewrite_data(protocol, error) \
- int protocol ## _rewrite_data(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * addr_new, ip46_address_t * addr_old, const hicn_faceid_t face_id, u8 reset_pl) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_current_header_length(protocol, error) \
+ int protocol##_get_current_header_length ( \
+ hicn_type_t type, const hicn_protocol_t *h, size_t *header_length) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_length(protocol, error) \
- int protocol ## _get_length(hicn_type_t type, const hicn_protocol_t * h, size_t * length) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_header_length(protocol, error) \
+ int protocol##_get_header_length ( \
+ hicn_type_t type, const hicn_protocol_t *h, size_t *header_length) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_current_header_length(protocol, error) \
- int protocol ## _get_current_header_length(hicn_type_t type, const hicn_protocol_t * h, size_t * header_length) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_payload_length(protocol, error) \
+ int protocol##_get_payload_length ( \
+ hicn_type_t type, const hicn_protocol_t *h, size_t *payload_length) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_header_length(protocol, error) \
- int protocol ## _get_header_length(hicn_type_t type, const hicn_protocol_t * h, size_t * header_length) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_payload_length(protocol, error) \
+ int protocol##_set_payload_length (hicn_type_t type, hicn_protocol_t *h, \
+ size_t payload_length) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_payload_length(protocol, error) \
- int protocol ## _get_payload_length(hicn_type_t type, const hicn_protocol_t * h, size_t * payload_length) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_signature_size(protocol, error) \
+ int protocol##_get_signature_size ( \
+ hicn_type_t type, const hicn_protocol_t *h, size_t *signature_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_payload_length(protocol, error) \
- int protocol ## _set_payload_length(hicn_type_t type, hicn_protocol_t * h, size_t payload_length) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_signature_size(protocol, error) \
+ int protocol##_set_signature_size (hicn_type_t type, hicn_protocol_t *h, \
+ size_t signature_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_signature_size(protocol, error) \
- int protocol ## _get_signature_size(hicn_type_t type, const hicn_protocol_t * h, size_t * signature_size) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_signature_gap(protocol, error) \
+ int protocol##_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, \
+ uint8_t signature_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_signature_size(protocol, error) \
- int protocol ## _set_signature_size(hicn_type_t type, hicn_protocol_t * h, size_t signature_size) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_signature_gap(protocol, error) \
+ int protocol##_get_signature_gap ( \
+ hicn_type_t type, const hicn_protocol_t *h, uint8_t *signature_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_signature_timestamp(protocol, error) \
- int protocol ## _set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h, uint64_t signature_timestamp) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_signature_timestamp(protocol, error) \
+ int protocol##_set_signature_timestamp ( \
+ hicn_type_t type, hicn_protocol_t *h, uint64_t signature_timestamp) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_signature_timestamp(protocol, error) \
- int protocol ## _get_signature_timestamp(hicn_type_t type, const hicn_protocol_t * h, uint64_t * signature_timestamp) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_signature_timestamp(protocol, error) \
+ int protocol##_get_signature_timestamp (hicn_type_t type, \
+ const hicn_protocol_t *h, \
+ uint64_t *signature_timestamp) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_validation_algorithm(protocol, error) \
- int protocol ## _set_validation_algorithm(hicn_type_t type, hicn_protocol_t * h, uint8_t validation_algorithm) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_validation_algorithm(protocol, error) \
+ int protocol##_set_validation_algorithm ( \
+ hicn_type_t type, hicn_protocol_t *h, uint8_t validation_algorithm) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_validation_algorithm(protocol, error) \
- int protocol ## _get_validation_algorithm(hicn_type_t type, const hicn_protocol_t * h, uint8_t * validation_algorithm) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_validation_algorithm(protocol, error) \
+ int protocol##_get_validation_algorithm (hicn_type_t type, \
+ const hicn_protocol_t *h, \
+ uint8_t *validation_algorithm) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_set_key_id(protocol, error) \
- int protocol ## _set_key_id(hicn_type_t type, hicn_protocol_t * h, uint8_t * key_id) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_set_key_id(protocol, error) \
+ int protocol##_set_key_id (hicn_type_t type, hicn_protocol_t *h, \
+ uint8_t *key_id) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_key_id(protocol, error) \
- int protocol ## _get_key_id(hicn_type_t type, hicn_protocol_t * h, uint8_t ** key_id, uint8_t *key_id_size) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_key_id(protocol, error) \
+ int protocol##_get_key_id (hicn_type_t type, hicn_protocol_t *h, \
+ uint8_t **key_id, uint8_t *key_id_size) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
-#define DECLARE_get_signature(protocol, error) \
- int protocol ## _get_signature(hicn_type_t type, hicn_protocol_t * h, uint8_t ** signature) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_get_signature(protocol, error) \
+ int protocol##_get_signature (hicn_type_t type, hicn_protocol_t *h, \
+ uint8_t **signature) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
#endif /* HICN_OPS_H */
diff --git a/lib/includes/hicn/protocol/ah.h b/lib/includes/hicn/protocol/ah.h
index a59a5051a..575da80d7 100644
--- a/lib/includes/hicn/protocol/ah.h
+++ b/lib/includes/hicn/protocol/ah.h
@@ -35,16 +35,19 @@
typedef struct
{
- u8 nh; // (to match with reserved in IPSEC AH)
- u8 payloadlen; // Len of signature/HMAC in 4-bytes words
+ u8 nh; // (to match with reserved in IPSEC AH)
+ u8 payloadlen; // Len of signature/HMAC in 4-bytes words (maximum size)
union
{
u16 reserved;
struct
{
- u8 validationAlgorithm; // As defined in parc_SignerAlgorithm.h
- u8 unused; // Unused (to match with reserved in IPSEC AH)
+ u8 validationAlgorithm; // As defined in parc_SignerAlgorithm.h
+ u8 signatureGap; // used to match IPSEC specification and to
+ // have the real size of the signature(without
+ // padding). It is the result of Maximum
+ // signature size - real size
};
};
union
@@ -60,12 +63,12 @@ typedef struct
u32 timestamp_as_u32[2];
};
// ICV would follow
- u8 keyId[32]; // Hash of the pub key
+ u8 keyId[32]; // Hash of pub key
/* 44 B + validationPayload */
- u8 validationPayload[0]; // Holds the signature
+ u8 validationPayload[0]; // Holds the signature
} _ah_header_t;
-#define AH_HDRLEN sizeof(_ah_header_t)
+#define AH_HDRLEN sizeof (_ah_header_t)
static_assert (EXPECTED_AH_HDRLEN == AH_HDRLEN,
"Size of AH Struct does not match its expected size.");
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
index f410e3d83..2588bde8b 100644
--- a/lib/src/CMakeLists.txt
+++ b/lib/src/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND LIBHICN_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/common.c
${CMAKE_CURRENT_SOURCE_DIR}/compat.c
diff --git a/lib/src/compat.c b/lib/src/compat.c
index 779a47315..932c11d9e 100644
--- a/lib/src/compat.c
+++ b/lib/src/compat.c
@@ -392,6 +392,22 @@ hicn_packet_set_signature_size (hicn_format_t format, hicn_header_t *h,
}
int
+hicn_packet_get_signature_gap (hicn_format_t format, const hicn_header_t *h,
+ uint8_t *bytes)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->get_signature_gap (type, &h->protocol, bytes);
+}
+
+int
+hicn_packet_set_signature_gap (hicn_format_t format, hicn_header_t *h,
+ uint8_t bytes)
+{
+ hicn_type_t type = hicn_format_to_type (format);
+ return hicn_ops_vft[type.l1]->set_signature_gap (type, &h->protocol, bytes);
+}
+
+int
hicn_packet_set_signature_timestamp (hicn_format_t format, hicn_header_t *h,
uint64_t signature_timestamp)
{
@@ -1041,8 +1057,8 @@ int
hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest,
const hicn_name_t *name)
{
- int ret_err =
- hicn_packet_reset_ece (format, interest); // interest packet -> ece flag unset
+ int ret_err = hicn_packet_reset_ece (
+ format, interest); // interest packet -> ece flag unset
if (ret_err < 0)
return HICN_LIB_ERROR_UNEXPECTED;
return hicn_packet_set_name (format, interest, name, _INTEREST);
@@ -1134,7 +1150,8 @@ int
hicn_data_set_name (hicn_format_t format, hicn_header_t *data,
const hicn_name_t *name)
{
- int ret_err = hicn_packet_set_ece (format, data); // data packet -> ece flag set
+ int ret_err =
+ hicn_packet_set_ece (format, data); // data packet -> ece flag set
if (ret_err < 0)
return HICN_LIB_ERROR_UNEXPECTED;
return hicn_packet_set_name (format, data, name, _DATA);
diff --git a/lib/src/ops.c b/lib/src/ops.c
index d49138398..ef12e9bf0 100644
--- a/lib/src/ops.c
+++ b/lib/src/ops.c
@@ -23,7 +23,6 @@
#endif
#include <stdlib.h>
#include <hicn/ops.h>
-
#include <hicn/header.h>
extern const hicn_ops_t hicn_ops_ipv4;
@@ -73,6 +72,8 @@ DECLARE_get_validation_algorithm (none, NONE);
DECLARE_set_key_id (none, NONE);
DECLARE_get_key_id (none, NONE);
DECLARE_get_signature (none, NONE);
+DECLARE_get_signature_gap (none, NONE);
+DECLARE_set_signature_gap (none, NONE);
DECLARE_HICN_OPS (none);
/**
@@ -81,11 +82,11 @@ DECLARE_HICN_OPS (none);
*/
const hicn_ops_t *const hicn_ops_vft[] = {
/* 0 */ [IPPROTO_IP] = &hicn_ops_ipv4,
- /* 1 */ [IPPROTO_ICMP] = &hicn_ops_icmp,
- /* 6 */ [IPPROTO_TCP] = &hicn_ops_tcp,
- /* 41 */ [IPPROTO_IPV6] = &hicn_ops_ipv6,
- /* 51 */ [IPPROTO_AH] = &hicn_ops_ah,
- /* 58 */ [IPPROTO_ICMPV6] = &hicn_ops_icmp,
+ /* 1 */[IPPROTO_ICMP] = &hicn_ops_icmp,
+ /* 6 */[IPPROTO_TCP] = &hicn_ops_tcp,
+ /* 41 */[IPPROTO_IPV6] = &hicn_ops_ipv6,
+ /* 51 */[IPPROTO_AH] = &hicn_ops_ah,
+ /* 58 */[IPPROTO_ICMPV6] = &hicn_ops_icmp,
[IPPROTO_NONE] = &hicn_ops_none,
};
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
index 03f3af04a..13340eae1 100644
--- a/lib/src/protocol/ah.c
+++ b/lib/src/protocol/ah.c
@@ -18,7 +18,7 @@
* @brief hICN operations for AH header
*/
-#include <string.h> // memcpy
+#include <string.h> // memcpy
#include <hicn/common.h>
#include <hicn/error.h>
#include <hicn/header.h>
@@ -31,8 +31,8 @@ DECLARE_get_interest_name (ah, UNEXPECTED);
DECLARE_set_interest_name (ah, UNEXPECTED);
DECLARE_get_interest_name_suffix (ah, UNEXPECTED);
DECLARE_set_interest_name_suffix (ah, UNEXPECTED);
-DECLARE_mark_packet_as_interest (ah, UNEXPECTED)
-DECLARE_mark_packet_as_data (ah, UNEXPECTED)
+DECLARE_mark_packet_as_interest (ah, UNEXPECTED);
+DECLARE_mark_packet_as_data (ah, UNEXPECTED);
DECLARE_get_data_locator (ah, UNEXPECTED);
DECLARE_set_data_locator (ah, UNEXPECTED);
DECLARE_get_data_name (ah, UNEXPECTED);
@@ -48,21 +48,20 @@ DECLARE_get_payload_length (ah, UNEXPECTED);
DECLARE_set_payload_length (ah, UNEXPECTED);
int
-ah_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+ah_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
{
/* *INDENT-OFF* */
- h->ah = (_ah_header_t)
- {
- .nh = (u8)0,
- .payloadlen = (u8)0,
- .reserved = (u16)0,
- };
+ h->ah = (_ah_header_t){
+ .nh = (u8) 0,
+ .payloadlen = (u8) 0,
+ .reserved = (u16) 0,
+ };
/* *INDENT-ON* */
return CHILD_OPS (init_packet_header, type, h);
}
int
-ah_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+ah_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
size_t signature_size;
int rc =
@@ -74,7 +73,7 @@ ah_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-ah_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+ah_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
size_t signature_size;
int rc =
@@ -86,7 +85,7 @@ ah_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-ah_update_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+ah_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
/* Nothing to do as there is no checksum in AH */
@@ -94,7 +93,7 @@ ah_update_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
}
int
-ah_verify_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+ah_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
/* Nothing to do as there is no checksum in AH */
@@ -102,17 +101,16 @@ ah_verify_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
}
int
-ah_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new,
- ip46_address_t * addr_old)
+ah_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new, ip46_address_t *addr_old)
{
/* Nothing to do on signature */
return HICN_LIB_ERROR_NONE;
}
int
-ah_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ah_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new, ip46_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
/* Nothing to do on signature */
@@ -120,22 +118,22 @@ ah_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
}
int
-ah_get_length (hicn_type_t type, const hicn_protocol_t * h, size_t * length)
+ah_get_length (hicn_type_t type, const hicn_protocol_t *h, size_t *length)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
}
int
-ah_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ah_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = AH_HDRLEN + (h->ah.payloadlen << 2);
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ah_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
size_t child_header_length = 0;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
@@ -146,22 +144,22 @@ ah_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ah_get_signature (hicn_type_t type, hicn_protocol_t * h, uint8_t ** signature)
+ah_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
{
*signature = h->ah.validationPayload;
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
- size_t * signature_size)
+ah_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size)
{
*signature_size = h->ah.payloadlen << 2;
return HICN_LIB_ERROR_NONE;
}
int
-ah_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ah_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
const size_t signature_size)
{
h->ah.payloadlen = (u8) (signature_size >> 2);
@@ -169,7 +167,7 @@ ah_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
}
int
-ah_set_signature_timestamp (hicn_type_t type, hicn_protocol_t * h,
+ah_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
uint64_t signature_timestamp)
{
uint64_t netwok_order_timestamp = htonll (signature_timestamp);
@@ -178,8 +176,8 @@ ah_set_signature_timestamp (hicn_type_t type, hicn_protocol_t * h,
}
int
-ah_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
- uint64_t * signature_timestamp)
+ah_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp)
{
memcpy (signature_timestamp, h->ah.timestamp_as_u8, sizeof (uint64_t));
*signature_timestamp = ntohll (*signature_timestamp);
@@ -187,7 +185,7 @@ ah_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ah_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
+ah_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
uint8_t validation_algorithm)
{
h->ah.validationAlgorithm = validation_algorithm;
@@ -195,23 +193,37 @@ ah_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
}
int
-ah_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
- uint8_t * validation_algorithm)
+ah_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm)
{
*validation_algorithm = h->ah.validationAlgorithm;
return HICN_LIB_ERROR_NONE;
}
int
-ah_set_key_id (hicn_type_t type, hicn_protocol_t * h, uint8_t * key_id)
+ah_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+{
+ h->ah.signatureGap = gap;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h, uint8_t *gap)
+{
+ *gap = h->ah.signatureGap;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+ah_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
{
memcpy (h->ah.keyId, key_id, sizeof (h->ah.keyId));
return HICN_LIB_ERROR_NONE;
}
int
-ah_get_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t ** key_id, uint8_t * key_id_size)
+ah_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size)
{
*key_id = h->ah.keyId;
*key_id_size = sizeof (h->ah.keyId);
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
index a16353427..5783cf52c 100644
--- a/lib/src/protocol/icmp.c
+++ b/lib/src/protocol/icmp.c
@@ -15,45 +15,47 @@
#include <string.h>
#include <hicn/protocol/icmp.h>
-
#include <hicn/error.h>
#include <hicn/ops.h>
-DECLARE_get_interest_locator (icmp, UNEXPECTED)
-DECLARE_set_interest_locator (icmp, UNEXPECTED)
-DECLARE_get_interest_name (icmp, UNEXPECTED)
-DECLARE_set_interest_name (icmp, UNEXPECTED)
-DECLARE_get_interest_name_suffix (icmp, UNEXPECTED)
-DECLARE_set_interest_name_suffix (icmp, UNEXPECTED)
-DECLARE_mark_packet_as_interest (icmp, UNEXPECTED)
-DECLARE_mark_packet_as_data (icmp, UNEXPECTED)
-DECLARE_get_data_locator (icmp, UNEXPECTED)
-DECLARE_set_data_locator (icmp, UNEXPECTED)
-DECLARE_get_data_name (icmp, UNEXPECTED)
-DECLARE_set_data_name (icmp, UNEXPECTED)
-DECLARE_get_data_name_suffix (icmp, UNEXPECTED)
-DECLARE_set_data_name_suffix (icmp, UNEXPECTED)
-DECLARE_get_data_pathlabel (icmp, UNEXPECTED)
-DECLARE_set_data_pathlabel (icmp, UNEXPECTED)
-DECLARE_update_data_pathlabel (icmp, UNEXPECTED)
-DECLARE_get_lifetime (icmp, UNEXPECTED)
-DECLARE_set_lifetime (icmp, UNEXPECTED)
-DECLARE_get_length (icmp, UNEXPECTED)
-DECLARE_get_payload_length (icmp, UNEXPECTED)
-DECLARE_set_payload_length (icmp, UNEXPECTED)
-DECLARE_get_signature (icmp, UNEXPECTED)
-
-int icmp_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
-{
- h->icmp = (_icmp_header_t)
- {
- .type = 0,.code = 0,.csum = 0,};
-
- return HICN_LIB_ERROR_NONE; // CHILD_OPS(init_packet_header, type, h->icmp);
-}
-
-int
-icmp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+DECLARE_get_interest_locator (icmp, UNEXPECTED);
+DECLARE_set_interest_locator (icmp, UNEXPECTED);
+DECLARE_get_interest_name (icmp, UNEXPECTED);
+DECLARE_set_interest_name (icmp, UNEXPECTED);
+DECLARE_get_interest_name_suffix (icmp, UNEXPECTED);
+DECLARE_set_interest_name_suffix (icmp, UNEXPECTED);
+DECLARE_mark_packet_as_interest (icmp, UNEXPECTED);
+DECLARE_mark_packet_as_data (icmp, UNEXPECTED);
+DECLARE_get_data_locator (icmp, UNEXPECTED);
+DECLARE_set_data_locator (icmp, UNEXPECTED);
+DECLARE_get_data_name (icmp, UNEXPECTED);
+DECLARE_set_data_name (icmp, UNEXPECTED);
+DECLARE_get_data_name_suffix (icmp, UNEXPECTED);
+DECLARE_set_data_name_suffix (icmp, UNEXPECTED);
+DECLARE_get_data_pathlabel (icmp, UNEXPECTED);
+DECLARE_set_data_pathlabel (icmp, UNEXPECTED);
+DECLARE_update_data_pathlabel (icmp, UNEXPECTED);
+DECLARE_get_lifetime (icmp, UNEXPECTED);
+DECLARE_set_lifetime (icmp, UNEXPECTED);
+DECLARE_get_length (icmp, UNEXPECTED);
+DECLARE_get_payload_length (icmp, UNEXPECTED);
+DECLARE_set_payload_length (icmp, UNEXPECTED);
+DECLARE_get_signature (icmp, UNEXPECTED);
+
+int
+icmp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
+{
+ h->icmp = (_icmp_header_t){
+ .type = 0,
+ .code = 0,
+ .csum = 0,
+ };
+
+ return HICN_LIB_ERROR_NONE; // CHILD_OPS(init_packet_header, type, h->icmp);
+}
+
+int
+icmp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
h->icmp.csum = 0;
@@ -61,7 +63,7 @@ icmp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-icmp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+icmp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
h->icmp.csum = 0;
@@ -69,93 +71,94 @@ icmp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-icmp_update_checksums (hicn_type_t type, hicn_protocol_t * h,
- u16 partial_csum, size_t payload_length)
+icmp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
-// h->icmp.csum = 0;
-// h->icmp.csum = csum(h->bytes, TCP_HDRLEN + payload_length, ~partial_csum);
-//
-// return CHILD_OPS(update_checksums, type, h->icmp, 0, payload_length);
+ // h->icmp.csum = 0;
+ // h->icmp.csum = csum(h->bytes, TCP_HDRLEN + payload_length,
+ // ~partial_csum);
+ //
+ // return CHILD_OPS(update_checksums, type, h->icmp, 0, payload_length);
}
int
-icmp_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
- u16 partial_csum, size_t payload_length)
+icmp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
-// if (csum(h->bytes, TCP_HDRLEN + payload_length, ~partial_csum) != 0)
-// return HICN_LIB_ERROR_CORRUPTED_PACKET;
-// return CHILD_OPS(verify_checksums, type, h->icmp, 0, payload_length);
+ // if (csum(h->bytes, TCP_HDRLEN + payload_length, ~partial_csum) != 0)
+ // return HICN_LIB_ERROR_CORRUPTED_PACKET;
+ // return CHILD_OPS(verify_checksums, type, h->icmp, 0, payload_length);
}
int
-icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new,
- ip46_address_t * addr_old)
+icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new,
+ ip46_address_t *addr_old)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
-// u16 *icmp_checksum = &(h->icmp.csum);
-//
-// /*
-// * Padding fields are set to zero so we can apply checksum on the
-// * whole struct by interpreting it as IPv6 in all cases
-// *
-// * v4 code would be:
-// * csum = ip_csum_sub_even (*icmp_checksum, h->ipv4.saddr.as_u32);
-// * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
-// */
-// u16 csum = ip_csum_sub_even (*icmp_checksum, h->ipv6.saddr.as_u64[0]);
-// csum = ip_csum_sub_even (csum, h->ipv6.saddr.as_u64[1]);
-// csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[0]);
-// csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[1]);
-//
-// *icmp_checksum = ip_csum_fold (csum);
-//
-// return HICN_LIB_ERROR_NONE;
-}
-
-int
-icmp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ // u16 *icmp_checksum = &(h->icmp.csum);
+ //
+ // /*
+ // * Padding fields are set to zero so we can apply checksum on the
+ // * whole struct by interpreting it as IPv6 in all cases
+ // *
+ // * v4 code would be:
+ // * csum = ip_csum_sub_even (*icmp_checksum, h->ipv4.saddr.as_u32);
+ // * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+ // */
+ // u16 csum = ip_csum_sub_even (*icmp_checksum, h->ipv6.saddr.as_u64[0]);
+ // csum = ip_csum_sub_even (csum, h->ipv6.saddr.as_u64[1]);
+ // csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[0]);
+ // csum = ip_csum_add_even (csum, h->ipv6.saddr.as_u64[1]);
+ //
+ // *icmp_checksum = ip_csum_fold (csum);
+ //
+ // return HICN_LIB_ERROR_NONE;
+}
+
+int
+icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new, ip46_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
-// u16 *icmp_checksum = &(h->icmp.csum);
-//
-// /*
-// * Padding fields are set to zero so we can apply checksum on the
-// * whole struct by interpreting it as IPv6 in all cases
-// *
-// * v4 code would be:
-// * csum = ip_csum_sub_even (*icmp_checksum, h->ipv4.saddr.as_u32);
-// * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
-// */
-// u16 csum = ip_csum_sub_even (*icmp_checksum, addr_old->ip6.as_u64[0]);
-// csum = ip_csum_sub_even (*icmp_checksum, addr_old->ip6.as_u64[1]);
-// csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[0]);
-// csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[1]);
-//
-// csum = ip_csum_sub_even (csum, h->icmp.pathlabel);
-// icmp_update_data_pathlabel(type, h, face_id);
-// csum = ip_csum_add_even (csum, h->icmp.pathlabel);
-//
-// *icmp_checksum = ip_csum_fold (csum);
-//
-// return HICN_LIB_ERROR_NONE;
-}
-
-int
-icmp_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ // u16 *icmp_checksum = &(h->icmp.csum);
+ //
+ // /*
+ // * Padding fields are set to zero so we can apply checksum on the
+ // * whole struct by interpreting it as IPv6 in all cases
+ // *
+ // * v4 code would be:
+ // * csum = ip_csum_sub_even (*icmp_checksum, h->ipv4.saddr.as_u32);
+ // * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
+ // */
+ // u16 csum = ip_csum_sub_even (*icmp_checksum, addr_old->ip6.as_u64[0]);
+ // csum = ip_csum_sub_even (*icmp_checksum, addr_old->ip6.as_u64[1]);
+ // csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[0]);
+ // csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[1]);
+ //
+ // csum = ip_csum_sub_even (csum, h->icmp.pathlabel);
+ // icmp_update_data_pathlabel(type, h, face_id);
+ // csum = ip_csum_add_even (csum, h->icmp.pathlabel);
+ //
+ // *icmp_checksum = ip_csum_fold (csum);
+ //
+ // return HICN_LIB_ERROR_NONE;
+}
+
+int
+icmp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = ICMP_HDRLEN;
return HICN_LIB_ERROR_NONE;
}
int
-icmp_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+icmp_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
size_t child_header_length = 0;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
@@ -167,57 +170,69 @@ icmp_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
}
int
-icmp_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
- size_t * signature_size)
+icmp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size)
{
return CHILD_OPS (get_signature_size, type, h, signature_size);
}
int
-icmp_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+icmp_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
size_t signature_size)
{
return CHILD_OPS (set_signature_size, type, h, signature_size);
}
int
-icmp_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
- uint64_t signature_timestamp)
+icmp_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+{
+ return CHILD_OPS (set_signature_gap, type, h, gap);
+}
+
+int
+icmp_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *gap)
+{
+ return CHILD_OPS (get_signature_gap, type, h, gap);
+}
+
+int
+icmp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+ uint64_t signature_timestamp)
{
return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
}
int
-icmp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
- uint64_t * signature_timestamp)
+icmp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp)
{
return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
}
int
-icmp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
- uint8_t validation_algorithm)
+icmp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t validation_algorithm)
{
return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
}
int
-icmp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
- uint8_t * validation_algorithm)
+icmp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm)
{
return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
}
int
-icmp_set_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t *key_id)
+icmp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
{
return CHILD_OPS (set_key_id, type, h, key_id);
}
int
-icmp_get_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t **key_id, uint8_t *key_id_size)
+icmp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size)
{
return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
}
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
index 73ce12ee0..cf50f9996 100644
--- a/lib/src/protocol/ipv4.c
+++ b/lib/src/protocol/ipv4.c
@@ -33,12 +33,12 @@
#include <hicn/header.h>
#include <hicn/protocol/ipv4.h>
-
-int ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * payload_length);
+typedef unsigned short u_short;
+int ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *payload_length);
int
-ipv4_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+ipv4_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
{
size_t total_header_length;
int rc =
@@ -46,37 +46,41 @@ ipv4_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
if (rc < 0)
return rc;
- h->ipv4 = (_ipv4_header_t)
- {
- .version_ihl =
- (IPV4_DEFAULT_VERSION << 4) | (0x0f & IPV4_DEFAULT_IHL),.tos =
- IPV4_DEFAULT_TOS,.len = htons ((u16) total_header_length),.id =
- htons (IPV4_DEFAULT_ID),.frag_off =
- htons (IPV4_DEFAULT_FRAG_OFF),.ttl = HICN_DEFAULT_TTL,.protocol =
- type.l2,.csum = 0,.saddr.as_u32 = 0,.daddr.as_u32 = 0,};
+ h->ipv4 = (_ipv4_header_t){
+ .version_ihl = (IPV4_DEFAULT_VERSION << 4) | (0x0f & IPV4_DEFAULT_IHL),
+ .tos = IPV4_DEFAULT_TOS,
+ .len = htons ((u16) total_header_length),
+ .id = htons (IPV4_DEFAULT_ID),
+ .frag_off = htons (IPV4_DEFAULT_FRAG_OFF),
+ .ttl = HICN_DEFAULT_TTL,
+ .protocol = type.l2,
+ .csum = 0,
+ .saddr.as_u32 = 0,
+ .daddr.as_u32 = 0,
+ };
return CHILD_OPS (init_packet_header, type, h);
}
int
-ipv4_get_interest_locator (hicn_type_t type, const hicn_protocol_t * h,
- ip46_address_t * ip_address)
+ipv4_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h,
+ ip46_address_t *ip_address)
{
ip_address->ip4 = h->ipv4.saddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_set_interest_locator (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * ip_address)
+ipv4_set_interest_locator (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *ip_address)
{
h->ipv4.saddr = ip_address->ip4;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_interest_name (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_t * name)
+ipv4_get_interest_name (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name)
{
name->ip4.prefix_as_ip4 = h->ipv4.daddr;
#ifndef HICN_VPP_PLUGIN
@@ -87,41 +91,41 @@ ipv4_get_interest_name (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv4_set_interest_name (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_t * name)
+ipv4_set_interest_name (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name)
{
h->ipv4.daddr = name->ip4.prefix_as_ip4;
return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip4.suffix));
}
int
-ipv4_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix)
+ipv4_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
{
return CHILD_OPS (get_interest_name_suffix, type, h, suffix);
}
int
-ipv4_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix)
+ipv4_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
{
return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
}
int
-ipv4_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t * h)
+ipv4_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
{
return CHILD_OPS (mark_packet_as_interest, type, h);
}
int
-ipv4_mark_packet_as_data (hicn_type_t type, hicn_protocol_t * h)
+ipv4_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
{
return CHILD_OPS (mark_packet_as_data, type, h);
}
int
-ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
/* Sets everything to 0 up to IP destination address */
memset (&(h->ipv4), 0, 16);
@@ -130,24 +134,24 @@ ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-ipv4_get_data_locator (hicn_type_t type, const hicn_protocol_t * h,
- ip46_address_t * ip_address)
+ipv4_get_data_locator (hicn_type_t type, const hicn_protocol_t *h,
+ ip46_address_t *ip_address)
{
ip_address->ip4 = h->ipv4.daddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_set_data_locator (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * ip_address)
+ipv4_set_data_locator (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *ip_address)
{
h->ipv4.daddr = ip_address->ip4;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_data_name (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_t * name)
+ipv4_get_data_name (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name)
{
name->ip4.prefix_as_ip4 = h->ipv4.saddr;
#ifndef HICN_VPP_PLUGIN
@@ -158,50 +162,50 @@ ipv4_get_data_name (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv4_set_data_name (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_t * name)
+ipv4_set_data_name (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name)
{
h->ipv4.saddr = name->ip4.prefix_as_ip4;
return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip4.suffix));
}
int
-ipv4_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix)
+ipv4_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
{
return CHILD_OPS (get_data_name_suffix, type, h, suffix);
}
int
-ipv4_set_data_name_suffix (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix)
+ipv4_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
{
return CHILD_OPS (set_data_name_suffix, type, h, suffix);
}
int
-ipv4_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t * h,
- u32 * pathlabel)
+ipv4_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
+ u32 *pathlabel)
{
return CHILD_OPS (get_data_pathlabel, type, h, pathlabel);
}
int
-ipv4_set_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ipv4_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
const u32 pathlabel)
{
return CHILD_OPS (set_data_pathlabel, type, h, pathlabel);
}
int
-ipv4_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ipv4_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
const hicn_faceid_t face_id)
{
return CHILD_OPS (update_data_pathlabel, type, h, face_id);
}
int
-ipv4_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+ipv4_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
/* Sets everything to 0 up to source address */
memset (&h->ipv4, 0, 12);
@@ -212,22 +216,22 @@ ipv4_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-ipv4_get_lifetime (hicn_type_t type, const hicn_protocol_t * h,
- hicn_lifetime_t * lifetime)
+ipv4_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_lifetime_t *lifetime)
{
return CHILD_OPS (get_lifetime, type, h, lifetime);
}
int
-ipv4_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
+ipv4_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
const hicn_lifetime_t lifetime)
{
return CHILD_OPS (set_lifetime, type, h, lifetime);
}
int
-ipv4_update_checksums (hicn_type_t type, hicn_protocol_t * h,
- u16 partial_csum, size_t payload_length)
+ipv4_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
{
/*
* Checksum field is not accounted for in lower layers, so we can compute
@@ -254,7 +258,8 @@ ipv4_update_checksums (hicn_type_t type, hicn_protocol_t * h,
ipv4_pseudo_header_t psh;
psh.ip_src = h->ipv4.saddr;
psh.ip_dst = h->ipv4.daddr;
- /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness
+ */
psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN);
psh.zero = 0;
psh.protocol = (u8) h->ipv4.protocol;
@@ -270,8 +275,8 @@ ipv4_update_checksums (hicn_type_t type, hicn_protocol_t * h,
}
int
-ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
- u16 partial_csum, size_t payload_length)
+ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
{
/*
* Checksum field is not accounted for in lower layers, so we can compute
@@ -292,7 +297,8 @@ ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
ipv4_pseudo_header_t psh;
psh.ip_src = h->ipv4.saddr;
psh.ip_dst = h->ipv4.daddr;
- /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness
+ */
psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN);
psh.zero = 0;
psh.protocol = (u8) h->ipv4.protocol;
@@ -304,9 +310,9 @@ ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
}
int
-ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new,
- ip46_address_t * addr_old)
+ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new,
+ ip46_address_t *addr_old)
{
// ASSERT(addr_old == NULL);
addr_old->ip4 = h->ipv4.saddr;
@@ -322,8 +328,8 @@ ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
}
int
-ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new, ip46_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
// ASSERT(addr_old == NULL);
@@ -336,36 +342,37 @@ ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
h->ipv4.csum = 0;
h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
- return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id, reset_pl);
+ return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id,
+ reset_pl);
}
int
-ipv4_get_current_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ipv4_get_current_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = IPV4_HDRLEN;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ipv4_get_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = h->ipv4.len;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ipv4_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = IPV4_HDRLEN;
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ipv4_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
size_t child_header_length = 0;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
@@ -376,8 +383,8 @@ ipv4_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * payload_length)
+ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *payload_length)
{
size_t child_header_length;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
@@ -388,76 +395,88 @@ ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv4_set_payload_length (hicn_type_t type, hicn_protocol_t * h,
+ipv4_set_payload_length (hicn_type_t type, hicn_protocol_t *h,
size_t payload_length)
{
size_t child_header_length;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
if (rc < 0)
return rc;
- h->ipv4.len = htons ((u_short) (payload_length + IPV4_HDRLEN + child_header_length));
+ h->ipv4.len =
+ htons ((u_short) (payload_length + IPV4_HDRLEN + child_header_length));
return HICN_LIB_ERROR_NONE;
}
int
-ipv4_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
- size_t * signature_size)
+ipv4_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size)
{
return CHILD_OPS (get_signature_size, type, h, signature_size);
}
int
-ipv4_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ipv4_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
size_t signature_size)
{
return CHILD_OPS (set_signature_size, type, h, signature_size);
}
int
-ipv4_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
- uint64_t signature_timestamp)
+ipv4_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+{
+ return CHILD_OPS (set_signature_gap, type, h, gap);
+}
+
+int
+ipv4_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *gap)
+{
+ return CHILD_OPS (get_signature_gap, type, h, gap);
+}
+
+int
+ipv4_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+ uint64_t signature_timestamp)
{
return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
}
int
-ipv4_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
- uint64_t * signature_timestamp)
+ipv4_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp)
{
return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
}
int
-ipv4_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
- uint8_t validation_algorithm)
+ipv4_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t validation_algorithm)
{
return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
}
int
-ipv4_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
- uint8_t * validation_algorithm)
+ipv4_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm)
{
return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
}
int
-ipv4_set_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t *key_id)
+ipv4_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
{
return CHILD_OPS (set_key_id, type, h, key_id);
}
int
-ipv4_get_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t **key_id, uint8_t *key_id_size)
+ipv4_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size)
{
return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
}
int
-ipv4_get_signature (hicn_type_t type, hicn_protocol_t * h,
- uint8_t ** signature)
+ipv4_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
{
return CHILD_OPS (get_signature, type, h, signature);
}
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
index bf8123497..7ac55b2be 100644
--- a/lib/src/protocol/ipv6.c
+++ b/lib/src/protocol/ipv6.c
@@ -15,17 +15,16 @@
#include <stdlib.h>
#include <string.h>
-
#include <hicn/common.h>
#include <hicn/error.h>
#include <hicn/ops.h>
-int
-ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * payload_length);
+typedef unsigned short u_short;
+int ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *payload_length);
int
-ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
{
size_t total_header_length;
int rc = CHILD_OPS (get_header_length, type, h, &total_header_length);
@@ -33,13 +32,12 @@ ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
return rc;
/* *INDENT-OFF* */
- h->ipv6 = (_ipv6_header_t)
- {
- .saddr = {{ 0 }}
- ,.daddr = {{ 0 }}
- ,.version_class_flow = htonl ((IPV6_DEFAULT_VERSION << 28) |
- (IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
- (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
+ h->ipv6 = (_ipv6_header_t){
+ .saddr = { { 0 } },
+ .daddr = { { 0 } },
+ .version_class_flow = htonl ((IPV6_DEFAULT_VERSION << 28) |
+ (IPV6_DEFAULT_TRAFFIC_CLASS << 20) |
+ (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)),
.len = htons ((u16) total_header_length),
.nxt = type.l2,
.hlim = HICN_DEFAULT_TTL,
@@ -49,24 +47,24 @@ ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
}
int
-ipv6_get_interest_locator (hicn_type_t type, const hicn_protocol_t * h,
- ip46_address_t * ip_address)
+ipv6_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h,
+ ip46_address_t *ip_address)
{
ip_address->ip6 = h->ipv6.saddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_set_interest_locator (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * ip_address)
+ipv6_set_interest_locator (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *ip_address)
{
h->ipv6.saddr = ip_address->ip6;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_interest_name (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_t * name)
+ipv6_get_interest_name (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name)
{
name->ip6.prefix_as_ip6 = h->ipv6.daddr;
#ifndef HICN_VPP_PLUGIN
@@ -77,41 +75,41 @@ ipv6_get_interest_name (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv6_set_interest_name (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_t * name)
+ipv6_set_interest_name (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name)
{
h->ipv6.daddr = name->ip6.prefix_as_ip6;
return CHILD_OPS (set_interest_name_suffix, type, h, &(name->ip6.suffix));
}
int
-ipv6_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix)
+ipv6_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
{
return CHILD_OPS (get_interest_name_suffix, type, h, suffix);
}
int
-ipv6_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix)
+ipv6_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
{
return CHILD_OPS (set_interest_name_suffix, type, h, suffix);
}
int
-ipv6_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t * h)
+ipv6_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
{
return CHILD_OPS (mark_packet_as_interest, type, h);
}
int
-ipv6_mark_packet_as_data (hicn_type_t type, hicn_protocol_t * h)
+ipv6_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
{
return CHILD_OPS (mark_packet_as_data, type, h);
}
int
-ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
/* Sets everything to 0 up to IP destination address */
memset (&(h->ipv6), 0, 24);
@@ -120,24 +118,24 @@ ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-ipv6_get_data_locator (hicn_type_t type, const hicn_protocol_t * h,
- ip46_address_t * ip_address)
+ipv6_get_data_locator (hicn_type_t type, const hicn_protocol_t *h,
+ ip46_address_t *ip_address)
{
ip_address->ip6 = h->ipv6.daddr;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_set_data_locator (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * ip_address)
+ipv6_set_data_locator (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *ip_address)
{
h->ipv6.daddr = ip_address->ip6;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_data_name (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_t * name)
+ipv6_get_data_name (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_t *name)
{
name->ip6.prefix_as_ip6 = h->ipv6.saddr;
#ifndef HICN_VPP_PLUGIN
@@ -148,50 +146,50 @@ ipv6_get_data_name (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv6_set_data_name (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_t * name)
+ipv6_set_data_name (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_t *name)
{
h->ipv6.saddr = name->ip6.prefix_as_ip6;
return CHILD_OPS (set_data_name_suffix, type, h, &(name->ip6.suffix));
}
int
-ipv6_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix)
+ipv6_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
{
return CHILD_OPS (get_data_name_suffix, type, h, suffix);
}
int
-ipv6_set_data_name_suffix (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix)
+ipv6_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
{
return CHILD_OPS (set_data_name_suffix, type, h, suffix);
}
int
-ipv6_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t * h,
- u32 * pathlabel)
+ipv6_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
+ u32 *pathlabel)
{
return CHILD_OPS (get_data_pathlabel, type, h, pathlabel);
}
int
-ipv6_set_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ipv6_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
const u32 pathlabel)
{
return CHILD_OPS (set_data_pathlabel, type, h, pathlabel);
}
int
-ipv6_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+ipv6_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
const hicn_faceid_t face_id)
{
return CHILD_OPS (update_data_pathlabel, type, h, face_id);
}
int
-ipv6_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+ipv6_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
/* IP: Set everithing to 0 up to destination address */
memset (&h->ipv6, 0, 8);
@@ -202,22 +200,22 @@ ipv6_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
}
int
-ipv6_get_lifetime (hicn_type_t type, const hicn_protocol_t * h,
- hicn_lifetime_t * lifetime)
+ipv6_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_lifetime_t *lifetime)
{
return CHILD_OPS (get_lifetime, type, h, lifetime);
}
int
-ipv6_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
+ipv6_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
const hicn_lifetime_t lifetime)
{
return CHILD_OPS (set_lifetime, type, h, lifetime);
}
int
-ipv6_update_checksums (hicn_type_t type, hicn_protocol_t * h,
- u16 partial_csum, size_t payload_length)
+ipv6_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
{
/* Retrieve payload length if not specified */
if (payload_length == ~0)
@@ -231,7 +229,8 @@ ipv6_update_checksums (hicn_type_t type, hicn_protocol_t * h,
ipv6_pseudo_header_t psh;
psh.ip_src = h->ipv6.saddr;
psh.ip_dst = h->ipv6.daddr;
- /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness
+ */
psh.size = htonl (ntohs (h->ipv6.len));
psh.zeros = 0;
psh.zero = 0;
@@ -248,8 +247,8 @@ ipv6_update_checksums (hicn_type_t type, hicn_protocol_t * h,
}
int
-ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
- u16 partial_csum, size_t payload_length)
+ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
+ size_t payload_length)
{
/* Retrieve payload length if not specified */
if (payload_length == ~0)
@@ -263,7 +262,8 @@ ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
ipv6_pseudo_header_t pseudo;
pseudo.ip_src = h->ipv6.saddr;
pseudo.ip_dst = h->ipv6.daddr;
- /* Size is u32 and not u16, we cannot copy and need to care about endianness */
+ /* Size is u32 and not u16, we cannot copy and need to care about endianness
+ */
pseudo.size = htonl (ntohs (h->ipv6.len));
pseudo.zeros = 0;
pseudo.zero = 0;
@@ -280,9 +280,9 @@ ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
}
int
-ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new,
- ip46_address_t * addr_old)
+ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new,
+ ip46_address_t *addr_old)
{
// ASSERT(addr_old == NULL);
addr_old->ip6 = h->ipv6.saddr;
@@ -292,36 +292,37 @@ ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
}
int
-ipv6_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new, ip46_address_t * addr_old,
+ipv6_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new, ip46_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
// ASSERT(addr_old == NULL);
addr_old->ip6 = h->ipv6.daddr;
h->ipv6.daddr = addr_new->ip6;
- return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id, reset_pl);
+ return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id,
+ reset_pl);
}
int
-ipv6_get_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ipv6_get_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = IPV6_HDRLEN + ntohs (h->ipv6.len);
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ipv6_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = IPV6_HDRLEN;
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+ipv6_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
size_t child_header_length = 0;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
@@ -332,8 +333,8 @@ ipv6_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * payload_length)
+ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *payload_length)
{
size_t child_header_length;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
@@ -344,76 +345,87 @@ ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t * h,
}
int
-ipv6_set_payload_length (hicn_type_t type, hicn_protocol_t * h,
+ipv6_set_payload_length (hicn_type_t type, hicn_protocol_t *h,
size_t payload_length)
{
size_t child_header_length;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
if (rc < 0)
return rc;
- h->ipv6.len = htons ( (u_short) (payload_length + child_header_length));
+ h->ipv6.len = htons ((u_short) (payload_length + child_header_length));
return HICN_LIB_ERROR_NONE;
}
int
-ipv6_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
- size_t * signature_size)
+ipv6_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size)
{
return CHILD_OPS (get_signature_size, type, h, signature_size);
}
int
-ipv6_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+ipv6_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
size_t signature_size)
{
return CHILD_OPS (set_signature_size, type, h, signature_size);
}
int
-ipv6_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
- uint64_t signature_timestamp)
+ipv6_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+{
+ return CHILD_OPS (set_signature_gap, type, h, gap);
+}
+
+int
+ipv6_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *gap)
+{
+ return CHILD_OPS (get_signature_gap, type, h, gap);
+}
+
+int
+ipv6_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+ uint64_t signature_timestamp)
{
return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
}
int
-ipv6_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
- uint64_t * signature_timestamp)
+ipv6_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp)
{
return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
}
int
-ipv6_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
- uint8_t validation_algorithm)
+ipv6_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t validation_algorithm)
{
return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
}
int
-ipv6_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
- uint8_t * validation_algorithm)
+ipv6_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm)
{
return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
}
int
-ipv6_set_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t *key_id)
+ipv6_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
{
return CHILD_OPS (set_key_id, type, h, key_id);
}
int
-ipv6_get_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t **key_id, uint8_t *key_id_size)
+ipv6_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size)
{
return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
}
int
-ipv6_get_signature (hicn_type_t type, hicn_protocol_t * h,
- uint8_t ** signature)
+ipv6_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
{
return CHILD_OPS (get_signature, type, h, signature);
}
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
index 95f93c6af..cfeac1907 100644
--- a/lib/src/protocol/tcp.c
+++ b/lib/src/protocol/tcp.c
@@ -15,23 +15,22 @@
#include <string.h>
#include <hicn/protocol/tcp.h>
-
#include <hicn/error.h>
#include <hicn/ops.h>
-#define TCP_DEFAULT_SRC_PORT 0x8000
-#define TCP_DEFAULT_DST_PORT 0x0080
-#define TCP_DEFAULT_WINDOW_SIZE 0 // In [2, 65535]
-#define TCP_DEFAULT_HLEN 20
-#define TCP_DEFAULT_DATA_OFFSET_RES (TCP_DEFAULT_HLEN >> 2) << 4
-#define TCP_DEFAULT_CWR 0
-#define TCP_DEFAULT_ECE 0
-#define TCP_DEFAULT_URG 0
-#define TCP_DEFAULT_ACK 0
-#define TCP_DEFAULT_PSH 0
-#define TCP_DEFAULT_RST 0
-#define TCP_DEFAULT_SYN 1
-#define TCP_DEFAULT_FIN 0
+#define TCP_DEFAULT_SRC_PORT 0x8000
+#define TCP_DEFAULT_DST_PORT 0x0080
+#define TCP_DEFAULT_WINDOW_SIZE 0 // In [2, 65535]
+#define TCP_DEFAULT_HLEN 20
+#define TCP_DEFAULT_DATA_OFFSET_RES (TCP_DEFAULT_HLEN >> 2) << 4
+#define TCP_DEFAULT_CWR 0
+#define TCP_DEFAULT_ECE 0
+#define TCP_DEFAULT_URG 0
+#define TCP_DEFAULT_ACK 0
+#define TCP_DEFAULT_PSH 0
+#define TCP_DEFAULT_RST 0
+#define TCP_DEFAULT_SYN 1
+#define TCP_DEFAULT_FIN 0
DECLARE_get_interest_locator (tcp, UNEXPECTED);
DECLARE_set_interest_locator (tcp, UNEXPECTED);
@@ -46,7 +45,7 @@ DECLARE_get_payload_length (tcp, UNEXPECTED);
DECLARE_set_payload_length (tcp, UNEXPECTED);
always_inline int
-check_tcp_checksum(u16 csum)
+check_tcp_checksum (u16 csum)
{
/* As per RFC1624
* In one's complement, there are two representations of zero: the all
@@ -68,18 +67,18 @@ check_tcp_checksum(u16 csum)
}
int
-tcp_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
+tcp_init_packet_header (hicn_type_t type, hicn_protocol_t *h)
{
- h->tcp = (_tcp_header_t) {
+ h->tcp = (_tcp_header_t){
.sport = htons (TCP_DEFAULT_SRC_PORT),
.dport = htons (TCP_DEFAULT_DST_PORT),
.seq = 0,
.seq_ack = 0,
.data_offset_and_reserved = TCP_DEFAULT_DATA_OFFSET_RES,
- .flags =
- TCP_DEFAULT_CWR << 7 | TCP_DEFAULT_ECE << 6 | TCP_DEFAULT_URG << 5 |
- TCP_DEFAULT_ACK << 4 | TCP_DEFAULT_PSH << 3 | TCP_DEFAULT_RST << 2 |
- TCP_DEFAULT_SYN << 1 | TCP_DEFAULT_FIN << 0,
+ .flags = TCP_DEFAULT_CWR << 7 | TCP_DEFAULT_ECE << 6 |
+ TCP_DEFAULT_URG << 5 | TCP_DEFAULT_ACK << 4 |
+ TCP_DEFAULT_PSH << 3 | TCP_DEFAULT_RST << 2 |
+ TCP_DEFAULT_SYN << 1 | TCP_DEFAULT_FIN << 0,
.window = htons (TCP_DEFAULT_WINDOW_SIZE),
.csum = 0xffff,
.urg_ptr = 65000,
@@ -93,16 +92,16 @@ tcp_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
}
int
-tcp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix)
+tcp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
{
*suffix = ntohl (h->tcp.name_suffix);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix)
+tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
{
h->tcp.name_suffix = htonl (*suffix);
@@ -110,21 +109,21 @@ tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
}
int
-tcp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t * h)
+tcp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h)
{
h->tcp.flags &= ~HICN_TCP_FLAG_ECE;
return HICN_LIB_ERROR_NONE;
}
int
-tcp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t * h)
+tcp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h)
{
h->tcp.flags |= HICN_TCP_FLAG_ECE;
return HICN_LIB_ERROR_NONE;
}
int
-tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
+tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
memset (&(h->tcp), 0, 4);
memset (&(h->tcp.seq_ack), 0, 12);
@@ -132,33 +131,32 @@ tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
return CHILD_OPS (reset_interest_for_hash, type, h);
}
-
int
-tcp_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t * h,
- hicn_name_suffix_t * suffix)
+tcp_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_name_suffix_t *suffix)
{
*suffix = ntohl (h->tcp.name_suffix);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t * h,
- const hicn_name_suffix_t * suffix)
+tcp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h,
+ const hicn_name_suffix_t *suffix)
{
h->tcp.name_suffix = htonl (*suffix);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t * h,
- u32 * pathlabel)
+tcp_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h,
+ u32 *pathlabel)
{
*pathlabel = h->tcp.seq_ack;
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+tcp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
const u32 pathlabel)
{
h->tcp.seq_ack = pathlabel;
@@ -166,7 +164,7 @@ tcp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
}
int
-tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
+tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h,
const hicn_faceid_t face_id)
{
hicn_pathlabel_t pl =
@@ -181,7 +179,7 @@ tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
}
int
-tcp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
+tcp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h)
{
memset (&(h->tcp), 0, 4);
memset (&(h->tcp.seq_ack), 0, 12);
@@ -189,18 +187,17 @@ tcp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t * h)
return CHILD_OPS (reset_data_for_hash, type, h);
}
-
int
-tcp_get_lifetime (hicn_type_t type, const hicn_protocol_t * h,
- hicn_lifetime_t * lifetime)
+tcp_get_lifetime (hicn_type_t type, const hicn_protocol_t *h,
+ hicn_lifetime_t *lifetime)
{
- *lifetime =
- ntohs (h->tcp.urg_ptr) << (h->tcp.data_offset_and_reserved & 0xF);
+ *lifetime = ntohs (h->tcp.urg_ptr)
+ << (h->tcp.data_offset_and_reserved & 0xF);
return HICN_LIB_ERROR_NONE;
}
int
-tcp_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
+tcp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
const hicn_lifetime_t lifetime)
{
u8 multiplier = 0;
@@ -210,13 +207,13 @@ tcp_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
{
h->tcp.urg_ptr = htons (HICN_MAX_LIFETIME_SCALED);
h->tcp.data_offset_and_reserved =
- (h->
- tcp.data_offset_and_reserved & ~0x0F) | HICN_MAX_LIFETIME_MULTIPLIER;
+ (h->tcp.data_offset_and_reserved & ~0x0F) |
+ HICN_MAX_LIFETIME_MULTIPLIER;
return HICN_LIB_ERROR_NONE;
}
- while (lifetime_scaled > HICN_MAX_LIFETIME_SCALED
- && multiplier <= HICN_MAX_LIFETIME_MULTIPLIER)
+ while (lifetime_scaled > HICN_MAX_LIFETIME_SCALED &&
+ multiplier <= HICN_MAX_LIFETIME_MULTIPLIER)
{
multiplier++;
lifetime_scaled = lifetime_scaled >> 1;
@@ -230,7 +227,7 @@ tcp_set_lifetime (hicn_type_t type, hicn_protocol_t * h,
}
int
-tcp_update_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+tcp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
h->tcp.csum = 0;
@@ -246,45 +243,46 @@ tcp_update_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
}
int
-tcp_verify_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
+tcp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
if (PREDICT_TRUE (partial_csum != 0))
{
partial_csum = ~partial_csum;
}
-
+
if (csum (h, TCP_HDRLEN + payload_length, partial_csum) != 0)
return HICN_LIB_ERROR_CORRUPTED_PACKET;
return CHILD_OPS (verify_checksums, type, h, 0, payload_length);
}
-#define TCP_OFFSET_MASK 13
-#define TCP_OFFSET_DATA_OFFSET 12
+#define TCP_OFFSET_MASK 13
+#define TCP_OFFSET_DATA_OFFSET 12
#define TCP_OFFSET_IN_BITS_DATA_OFFSET 0
#define TCP_OFFSET_IN_BITS_RESERVED 4
-#define TCP_OFFSET_IN_BITS_NS 7
-
-#define TCP_DEFAULT_SRC_PORT 0x8000
-#define TCP_DEFAULT_DST_PORT 0x0080
-#define TCP_DEFAULT_WINDOW_SIZE 0 // In [2, 65535]
-#define TCP_DEFAULT_DATA_OFFSET 5 // Size of the TCP header in words (= 4 bytes). Must be greater or equal than 5.
-#define TCP_DEFAULT_CWR 0
-#define TCP_DEFAULT_ECE 0
-#define TCP_DEFAULT_URG 0
-#define TCP_DEFAULT_ACK 0
-#define TCP_DEFAULT_PSH 0
-#define TCP_DEFAULT_RST 0
-#define TCP_DEFAULT_SYN 1
-#define TCP_DEFAULT_FIN 0
+#define TCP_OFFSET_IN_BITS_NS 7
+
+#define TCP_DEFAULT_SRC_PORT 0x8000
+#define TCP_DEFAULT_DST_PORT 0x0080
+#define TCP_DEFAULT_WINDOW_SIZE 0 // In [2, 65535]
+#define TCP_DEFAULT_DATA_OFFSET \
+ 5 // Size of the TCP header in words (= 4 bytes). Must be greater or equal
+ // than 5.
+#define TCP_DEFAULT_CWR 0
+#define TCP_DEFAULT_ECE 0
+#define TCP_DEFAULT_URG 0
+#define TCP_DEFAULT_ACK 0
+#define TCP_DEFAULT_PSH 0
+#define TCP_DEFAULT_RST 0
+#define TCP_DEFAULT_SYN 1
+#define TCP_DEFAULT_FIN 0
int
-tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new,
- ip46_address_t * addr_old)
+tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new, ip46_address_t *addr_old)
{
u16 *tcp_checksum = &(h->tcp.csum);
- int ret = check_tcp_checksum(*tcp_checksum);
+ int ret = check_tcp_checksum (*tcp_checksum);
if (ret)
{
@@ -299,7 +297,8 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
* csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32);
* csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
*/
- ip_csum_t csum = ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (h->ipv6.saddr.as_u64[0]));
+ ip_csum_t csum =
+ ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (h->ipv6.saddr.as_u64[0]));
csum = ip_csum_sub_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[1]));
csum = ip_csum_add_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[0]));
csum = ip_csum_add_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[1]));
@@ -310,19 +309,20 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
}
int
-tcp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
- const ip46_address_t * addr_new, ip46_address_t * addr_old,
+tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h,
+ const ip46_address_t *addr_new, ip46_address_t *addr_old,
const hicn_faceid_t face_id, u8 reset_pl)
{
u16 *tcp_checksum = &(h->tcp.csum);
- int ret = check_tcp_checksum(*tcp_checksum);
+ int ret = check_tcp_checksum (*tcp_checksum);
/*
* update path label
*/
u16 old_pl = h->tcp.seq_ack;
- if(reset_pl) h->tcp.seq_ack = 0;
+ if (reset_pl)
+ h->tcp.seq_ack = 0;
tcp_update_data_pathlabel (type, h, face_id);
if (ret)
@@ -338,8 +338,10 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
* csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32);
* csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32);
*/
- ip_csum_t csum = ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[0]));
- csum = ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[1]));
+ ip_csum_t csum =
+ ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[0]));
+ csum =
+ ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->ip6.as_u64[1]));
csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[0]));
csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[1]));
@@ -352,16 +354,16 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
}
int
-tcp_get_current_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+tcp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
*header_length = TCP_HDRLEN;
return HICN_LIB_ERROR_NONE;
}
int
-tcp_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
- size_t * header_length)
+tcp_get_header_length (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *header_length)
{
size_t child_header_length = 0;
int rc = CHILD_OPS (get_header_length, type, h, &child_header_length);
@@ -373,64 +375,75 @@ tcp_get_header_length (hicn_type_t type, const hicn_protocol_t * h,
}
int
-tcp_get_signature_size (hicn_type_t type, const hicn_protocol_t * h,
- size_t * signature_size)
+tcp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h,
+ size_t *signature_size)
{
return CHILD_OPS (get_signature_size, type, h, signature_size);
}
int
-tcp_set_signature_size (hicn_type_t type, hicn_protocol_t * h,
+tcp_set_signature_size (hicn_type_t type, hicn_protocol_t *h,
size_t signature_size)
{
return CHILD_OPS (set_signature_size, type, h, signature_size);
}
int
-tcp_set_signature_timestamp(hicn_type_t type, hicn_protocol_t * h,
- uint64_t signature_timestamp)
+tcp_set_signature_gap (hicn_type_t type, hicn_protocol_t *h, uint8_t gap)
+{
+ return CHILD_OPS (set_signature_gap, type, h, gap);
+}
+
+int
+tcp_get_signature_gap (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *gap)
+{
+ return CHILD_OPS (get_signature_gap, type, h, gap);
+}
+
+int
+tcp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h,
+ uint64_t signature_timestamp)
{
return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp);
}
int
-tcp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t * h,
- uint64_t * signature_timestamp)
+tcp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h,
+ uint64_t *signature_timestamp)
{
return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp);
}
int
-tcp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t * h,
- uint8_t validation_algorithm)
+tcp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h,
+ uint8_t validation_algorithm)
{
return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm);
}
int
-tcp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t * h,
- uint8_t * validation_algorithm)
+tcp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h,
+ uint8_t *validation_algorithm)
{
return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm);
}
int
-tcp_set_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t *key_id)
+tcp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id)
{
return CHILD_OPS (set_key_id, type, h, key_id);
}
int
-tcp_get_key_id (hicn_type_t type, hicn_protocol_t * h,
- uint8_t **key_id, uint8_t *key_id_size)
+tcp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id,
+ uint8_t *key_id_size)
{
return CHILD_OPS (get_key_id, type, h, key_id, key_id_size);
}
int
-tcp_get_signature (hicn_type_t type, hicn_protocol_t * h,
- uint8_t ** signature)
+tcp_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature)
{
return CHILD_OPS (get_signature, type, h, signature);
}
diff --git a/libtransport/CMakeLists.txt b/libtransport/CMakeLists.txt
index d94f2859b..a5009f353 100644
--- a/libtransport/CMakeLists.txt
+++ b/libtransport/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Copyright (c) 2017-2021 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
@@ -11,7 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+# CMake 3.11 required to use FetchContent
+cmake_minimum_required(VERSION 3.11 FATAL_ERROR)
project(libtransport)
@@ -29,37 +30,23 @@ if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif ()
-#########################################
-# LOG LEVELS AVAILABLE
-# VERBOSE
-# DEBUG
-# INFO
-# WARN
-# ERROR
-# FATAL
-# NONE
-#
-# Default: INFO
-set(TRANSPORT_LOG_LEVEL "INFO" CACHE STRING "Set log level")
-
set(TRANSPORT_ROOT_PATH "src")
set(LIBTRANSPORT hicntransport)
+set(LIBTRANSPORT_COMPONENT libhicntransport)
+
if ((BUILD_HICNPLUGIN OR BUILD_MEMIF_CONNECTOR) AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(__vpp__ 1)
endif ()
set(LIBTRANSPORT ${LIBTRANSPORT} CACHE INTERNAL "" FORCE)
-if (NOT WIN32)
set(LIBTRANSPORT_SHARED ${LIBTRANSPORT}.shared CACHE INTERNAL "" FORCE)
-endif ()
set(LIBTRANSPORT_STATIC ${LIBTRANSPORT}.static CACHE INTERNAL "" FORCE)
set(LIBTRANSPORT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src CACHE INTERNAL "" FORCE)
include(WindowsMacros)
include(IosMacros)
-find_package_wrapper(Libparc REQUIRED)
find_package_wrapper(Asio REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(Threads REQUIRED)
@@ -81,42 +68,38 @@ else()
else()
set(HICN_LIBRARIES ${LIBHICN_SHARED})
list(APPEND DEPENDENCIES
-
${LIBHICN_SHARED}
)
endif()
endif()
-if (WIN32)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4275 /wd4996 /wd4311 /wd4302")
- if (CMAKE_BUILD_TYPE EQUAL "RELEASE")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:\"MSVCRTD\"" )
- endif ()
-endif ()
+
include(Packaging)
-list(APPEND LIBRARIES
- ${HICN_LIBRARIES}
- ${LIBPARC_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- ${VPP_LIBRARIES}
- ${ANDROID_LIBRARIES}
- ${OPENSSL_LIBRARIES}
- ${WINDOWS_LIBRARIES}
- ${LIBCONFIG_CPP_LIBRARIES}
-)
+add_subdirectory(third-party)
-set(LIBTRANSPORT_LIBRARIES_LIST "${LIBPARC_LIBRARIES};${CMAKE_THREAD_LIBS_INIT};${VPP_LIBRARIES};${ANDROID_LIBRARIES};${OPENSSL_LIBRARIES};${WINDOWS_LIBRARIES};${LIBCONFIG_CPP_LIBRARIES}" CACHE INTERNAL "LIBTRANSPORT_LIBRARIES_LIST")
+set(LIBRARIES
+ PRIVATE ${HICN_LIBRARIES}
+ PRIVATE ${CMAKE_THREAD_LIBS_INIT}
+ PRIVATE ${CMAKE_DL_LIBS}
+ PRIVATE ${OPENSSL_LIBRARIES}
+ PRIVATE ${LIBCONFIG_CPP_LIBRARIES}
+ PRIVATE ${THIRD_PARTY_LIBRARIES}
+)
# Include dirs -- Order does matter!
list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
${HICN_INCLUDE_DIRS}
${HICNPLUGIN_INCLUDE_DIRS}
- ${LIBPARC_INCLUDE_DIRS}
${CMAKE_THREADS_INCLUDE_DIRS}
${ASIO_INCLUDE_DIRS}
${WINDOWS_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
${CONFIG_INCLUDE_DIRS}
+ ${THIRD_PARTY_INCLUDE_DIRS}
+)
+
+list(APPEND DEPENDENCIES
+ ${THIRD_PARTY_DEPENDENCIES}
)
add_subdirectory(includes/hicn/transport)
diff --git a/libtransport/cmake/Modules/DefaultConfiguration.cmake b/libtransport/cmake/Modules/DefaultConfiguration.cmake
index 93dd90164..402ad86f5 100644
--- a/libtransport/cmake/Modules/DefaultConfiguration.cmake
+++ b/libtransport/cmake/Modules/DefaultConfiguration.cmake
@@ -12,7 +12,7 @@
# limitations under the License.
# C/c++ standard
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)
# Compilation flags
diff --git a/libtransport/cmake/Modules/Ios.cmake b/libtransport/cmake/Modules/Ios.cmake
index a4e625e98..1b2aae2bf 100644
--- a/libtransport/cmake/Modules/Ios.cmake
+++ b/libtransport/cmake/Modules/Ios.cmake
@@ -15,9 +15,6 @@ function (configure_ios_environment)
find_host_package ( OpenSSL REQUIRED )
include_directories(extras/iOS)
- find_host_package(Libparc REQUIRED)
- include_directories(${LIBPARC_INCLUDE_DIRS})
-
find_host_package(Libhicn REQUIRED)
include_directories(${HICN_INCLUDE_DIRS})
endfunction() \ No newline at end of file
diff --git a/libtransport/cmake/Modules/Packaging.cmake b/libtransport/cmake/Modules/Packaging.cmake
index e24172661..c885c6911 100644
--- a/libtransport/cmake/Modules/Packaging.cmake
+++ b/libtransport/cmake/Modules/Packaging.cmake
@@ -17,60 +17,51 @@
# Packages section
######################
-set(lib${LIBTRANSPORT}_DESCRIPTION
+set(${LIBTRANSPORT_COMPONENT}_DESCRIPTION
"Libhicn-transport provides transport services and \
socket API for applications willing to communicate \
using the hICN protocol stack."
CACHE STRING "Description for deb/rpm package."
)
-set(lib${LIBTRANSPORT}-dev_DESCRIPTION ${lib${LIBTRANSPORT}_DESCRIPTION}
- CACHE STRING "Description for deb/rpm package.")
-set(lib${LIBTRANSPORT}-devel_DESCRIPTION ${lib${LIBTRANSPORT}_DESCRIPTION}
- CACHE STRING "Description for deb/rpm package.")
-
-if ((BUILD_MEMIF_CONNECTOR OR BUILD_HICNPLUGIN) AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
-
- set(lib${LIBTRANSPORT}_DEB_DEPENDENCIES
- "lib${LIBHICN} (>= stable_version), libparc (>= 1.0), libmemif (>= stable_version), vpp (>= stable_version-release), vpp (<< next_version-release), hicn-plugin (>= stable_version)"
- CACHE STRING "Dependencies for deb/rpm package."
- )
-
- set(lib${LIBTRANSPORT}_RPM_DEPENDENCIES
- "lib${LIBHICN} >= stable_version, libparc >= 1.0, libmemif >= stable_version, vpp >= stable_version-release, vpp < next_version-release, hicn-plugin >= stable_version"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBTRANSPORT_COMPONENT}-dev_DESCRIPTION
+ CACHE STRING "Header files for developing using libhicntransport."
+)
- set(lib${LIBTRANSPORT}-dev_DEB_DEPENDENCIES
- "lib${LIBTRANSPORT} (>= stable_version), libasio-dev (>= 1.10), libhicn-dev (>= stable_version), libmemif-dev (>= stable_version), libparc-dev (>= 1.0), vpp-dev (>= stable_version-release), vpp-dev (<< next_version-release), hicn-plugin-dev (>= stable_version)"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(lib${LIBTRANSPORT}-devel_DESCRIPTION
+ CACHE STRING "Header files for developing using libhicntransport."
+)
- set(lib${LIBTRANSPORT}-dev_RPM_DEPENDENCIES
- "lib${LIBTRANSPORT} >= stable_version, asio-devel >= 1.10, lib${LIBHICN}-devel >= stable_version, libmemif-devel >= stable_version, libparc-devel >= 1.0, vpp-devel >= stable_version-release, vpp-devel < next_version-release, hicn-plugin-dev >= stable_version"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBTRANSPORT_COMPONENT}-io-modules_DESCRIPTION
+ CACHE STRING "Additional io modules for libhicntransport, including the memif connector for vpp."
+)
-else()
+set(${LIBTRANSPORT_COMPONENT}_DEB_DEPENDENCIES
+ "lib${LIBHICN} (>= stable_version), libparc (>= 1.0), libconfig++9v5 (>= 1.5-0.4build1)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(lib${LIBTRANSPORT}_DEB_DEPENDENCIES
- "lib${LIBHICN} (>= stable_version), libparc (>= 1.0)"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBTRANSPORT_COMPONENT}_RPM_DEPENDENCIES
+ "lib${LIBHICN} >= stable_version, libparc >= 1.0, libconfig >= 1.5-9.el8"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(lib${LIBTRANSPORT}_RPM_DEPENDENCIES
- "lib${LIBHICN} >= stable_version, libparc >= 1.0"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBTRANSPORT_COMPONENT}-dev_DEB_DEPENDENCIES
+ "${LIBTRANSPORT} (>= stable_version), libasio-dev (>= 1.10), lib${LIBHICN}-dev (>= stable_version), libparc-dev (>= 1.0), libconfig++-dev (>= 1.5-0.4build1)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(lib${LIBTRANSPORT}-dev_DEB_DEPENDENCIES
- "lib${LIBTRANSPORT} (>= stable_version), libasio-dev (>= 1.10), lib${LIBHICN}-dev (>= stable_version), libparc-dev (>= 1.0)"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBTRANSPORT_COMPONENT}-dev_RPM_DEPENDENCIES
+ "${LIBTRANSPORT} >= stable_version, asio-devel >= 1.10, lib${LIBHICN}-devel >= stable_version, libparc-devel >= 1.0, libconfig-devel >= 1.5-9.el8"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
- set(lib${LIBTRANSPORT}-dev_RPM_DEPENDENCIES
- "lib${LIBTRANSPORT} >= stable_version, asio-devel >= 1.10, lib${LIBHICN}-devel >= stable_version, libparc-devel >= 1.0"
- CACHE STRING "Dependencies for deb/rpm package."
- )
+set(${LIBTRANSPORT_COMPONENT}-io-modules_DEB_DEPENDENCIES
+ "${LIBTRANSPORT} (>= stable_version), libmemif (>= stable_version), vpp (>= stable_version-release), vpp (<< next_version-release), hicn-plugin (>= stable_version)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
-endif() \ No newline at end of file
+set(${LIBTRANSPORT_COMPONENT}-io-modules_RPM_DEPENDENCIES
+ "${LIBTRANSPORT} >= stable_version, libmemif >= stable_version, vpp >= stable_version-release, vpp < next_version-release, hicn-plugin >= stable_version"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
diff --git a/libtransport/includes/hicn/transport/CMakeLists.txt b/libtransport/includes/hicn/transport/CMakeLists.txt
index ca53bdffd..eb339fb5a 100644
--- a/libtransport/includes/hicn/transport/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
include(GNUInstallDirs)
set(ASIO_STANDALONE 1)
diff --git a/libtransport/includes/hicn/transport/auth/CMakeLists.txt b/libtransport/includes/hicn/transport/auth/CMakeLists.txt
index d855125b0..1e9fe4698 100644
--- a/libtransport/includes/hicn/transport/auth/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/auth/CMakeLists.txt
@@ -11,13 +11,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/common.h
${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.h
- ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash_type.h
- ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hasher.h
${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.h
${CMAKE_CURRENT_SOURCE_DIR}/identity.h
${CMAKE_CURRENT_SOURCE_DIR}/key_id.h
diff --git a/libtransport/includes/hicn/transport/auth/common.h b/libtransport/includes/hicn/transport/auth/common.h
index 911bcbc6a..fb0e82eb7 100644
--- a/libtransport/includes/hicn/transport/auth/common.h
+++ b/libtransport/includes/hicn/transport/auth/common.h
@@ -20,8 +20,6 @@
namespace transport {
namespace auth {
-using Hash = std::vector<uint8_t>;
-using HashEntry = std::pair<CryptoHashType, Hash>;
using PacketPtr = core::Packet *;
using Suffix = uint32_t;
diff --git a/libtransport/includes/hicn/transport/auth/crypto_hash.h b/libtransport/includes/hicn/transport/auth/crypto_hash.h
index 26c251b38..90f1627e9 100644
--- a/libtransport/includes/hicn/transport/auth/crypto_hash.h
+++ b/libtransport/includes/hicn/transport/auth/crypto_hash.h
@@ -16,105 +16,86 @@
#pragma once
#include <hicn/transport/errors/runtime_exception.h>
-#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/auth/crypto_hash_type.h>
-#include <hicn/transport/utils/array.h>
+#include <hicn/transport/utils/membuf.h>
-extern "C" {
-#include <parc/security/parc_CryptoHash.h>
-};
+#include <iomanip>
-#include <cstring>
-#include <unordered_map>
+extern "C" {
+#include <openssl/evp.h>
+}
namespace transport {
namespace auth {
-class CryptoHasher;
+typedef const EVP_MD *(*CryptoHashEVP)(void);
-struct EnumClassHash {
- template <typename T>
- std::size_t operator()(T t) const {
- return static_cast<std::size_t>(t);
- }
+enum class CryptoHashType : uint8_t {
+ UNKNOWN,
+ SHA256,
+ SHA512,
+ BLAKE2B512,
+ BLAKE2S256,
};
-static std::unordered_map<CryptoHashType, std::size_t, EnumClassHash>
- hash_size_map = {{CryptoHashType::SHA_256, 32},
- {CryptoHashType::CRC32C, 4},
- {CryptoHashType::SHA_512, 64}};
+class CryptoHash {
+ public:
+ // Constructors
+ CryptoHash();
+ CryptoHash(const CryptoHash &other);
+ CryptoHash(CryptoHash &&other);
+ CryptoHash(CryptoHashType hash_type);
+ CryptoHash(const uint8_t *hash, std::size_t size, CryptoHashType hash_type);
+ CryptoHash(const std::vector<uint8_t> &hash, CryptoHashType hash_type);
-class Signer;
-class Verifier;
+ // Destructor
+ ~CryptoHash() = default;
-class CryptoHash {
- friend class CryptoHasher;
- friend class Signer;
- friend class Verifier;
+ // Operators
+ CryptoHash &operator=(const CryptoHash &other);
+ bool operator==(const CryptoHash &other) const;
- public:
- CryptoHash() : hash_(nullptr) {}
-
- CryptoHash(const CryptoHash& other) {
- if (other.hash_) {
- hash_ = parcCryptoHash_Acquire(other.hash_);
- }
- }
-
- CryptoHash(CryptoHash&& other) {
- if (other.hash_) {
- hash_ = parcCryptoHash_Acquire(other.hash_);
- }
- }
-
- template <typename T>
- CryptoHash(const T* buffer, std::size_t length, CryptoHashType hash_type) {
- hash_ = parcCryptoHash_CreateFromArray(
- static_cast<PARCCryptoHashType>(hash_type), buffer, length);
- }
-
- ~CryptoHash() {
- if (hash_) {
- parcCryptoHash_Release(&hash_);
- }
- }
-
- CryptoHash& operator=(const CryptoHash& other) {
- if (other.hash_) {
- hash_ = parcCryptoHash_Acquire(other.hash_);
- }
-
- return *this;
- }
-
- template <typename T>
- utils::Array<T> getDigest() const {
- return utils::Array<T>(
- static_cast<T*>(parcBuffer_Overlay(parcCryptoHash_GetDigest(hash_), 0)),
- parcBuffer_Remaining(parcCryptoHash_GetDigest(hash_)));
- }
-
- CryptoHashType getType() {
- return static_cast<CryptoHashType>(parcCryptoHash_GetDigestType(hash_));
- }
-
- template <typename T>
- static bool compareBinaryDigest(const T* digest1, const T* digest2,
- CryptoHashType hash_type) {
- if (hash_size_map.find(hash_type) == hash_size_map.end()) {
- return false;
- }
-
- return !static_cast<bool>(
- std::memcmp(digest1, digest2, hash_size_map[hash_type]));
- }
-
- TRANSPORT_ALWAYS_INLINE void display() {
- parcBuffer_Display(parcCryptoHash_GetDigest(hash_), 2);
- }
+ // Compute the hash of given buffer
+ void computeDigest(const uint8_t *buffer, std::size_t len);
+ void computeDigest(const std::vector<uint8_t> &buffer);
+
+ // Compute the hash of given membuf
+ void computeDigest(const utils::MemBuf *buffer);
+
+ // Return the computed hash
+ std::vector<uint8_t> getDigest() const;
+
+ // Return the computed hash as a string
+ std::string getStringDigest() const;
+
+ // Return hash type
+ CryptoHashType getType() const;
+
+ // Return hash size
+ std::size_t getSize() const;
+
+ // Change hash type
+ void setType(CryptoHashType hash_type);
+
+ // Print hash to stdout
+ void display();
+
+ // Reset hash
+ void reset();
+
+ // Return OpenSSL EVP function associated to a given hash type
+ static CryptoHashEVP getEVP(CryptoHashType hash_type);
+
+ // Return hash size
+ static std::size_t getSize(CryptoHashType hash_type);
+
+ // Compare two raw buffers
+ static bool compareDigest(const uint8_t *h1, const uint8_t *h2,
+ CryptoHashType hash_type);
private:
- PARCCryptoHash* hash_;
+ CryptoHashType digest_type_;
+ std::vector<uint8_t> digest_;
+ std::size_t digest_size_;
};
} // namespace auth
diff --git a/libtransport/includes/hicn/transport/auth/crypto_hash_type.h b/libtransport/includes/hicn/transport/auth/crypto_hash_type.h
deleted file mode 100644
index 9d792624e..000000000
--- a/libtransport/includes/hicn/transport/auth/crypto_hash_type.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-extern "C" {
-#include <parc/security/parc_CryptoHashType.h>
-};
-
-#include <cstdint>
-
-namespace transport {
-namespace auth {
-
-enum class CryptoHashType : uint8_t {
- SHA_256 = PARCCryptoHashType_SHA256,
- SHA_512 = PARCCryptoHashType_SHA512,
- CRC32C = PARCCryptoHashType_CRC32C,
- NULL_HASH = PARCCryptoHashType_NULL
-};
-
-} // namespace auth
-} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/crypto_hasher.h b/libtransport/includes/hicn/transport/auth/crypto_hasher.h
deleted file mode 100644
index ada1a6ee8..000000000
--- a/libtransport/includes/hicn/transport/auth/crypto_hasher.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/auth/crypto_hash.h>
-
-extern "C" {
-#include <parc/security/parc_CryptoHasher.h>
-};
-
-namespace transport {
-namespace auth {
-
-class CryptoHasher {
- public:
- CryptoHasher(CryptoHashType hash_type)
- : hasher_(parcCryptoHasher_Create(
- static_cast<PARCCryptoHashType>(hash_type))),
- managed_(true) {}
-
- CryptoHasher(PARCCryptoHasher* hasher) : hasher_(hasher), managed_(false) {}
-
- ~CryptoHasher() {
- if (managed_) {
- parcCryptoHasher_Release(&hasher_);
- }
- }
-
- CryptoHasher& init() {
- if (parcCryptoHasher_Init(hasher_) == -1) {
- throw errors::RuntimeException("Cryptohash init failed.");
- }
-
- return *this;
- }
-
- template <typename T>
- CryptoHasher& updateBytes(const T* buffer, std::size_t length) {
- if (parcCryptoHasher_UpdateBytes(hasher_, buffer, length) == -1) {
- throw errors::RuntimeException("Cryptohash updateBytes failed.");
- }
- return *this;
- }
-
- CryptoHash finalize() {
- CryptoHash hash;
- hash.hash_ = parcCryptoHasher_Finalize(hasher_);
- return hash;
- }
-
- private:
- PARCCryptoHasher* hasher_;
- bool managed_;
-};
-
-} // namespace auth
-} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/crypto_suite.h b/libtransport/includes/hicn/transport/auth/crypto_suite.h
index 11df6ac06..d0f1de395 100644
--- a/libtransport/includes/hicn/transport/auth/crypto_suite.h
+++ b/libtransport/includes/hicn/transport/auth/crypto_suite.h
@@ -15,25 +15,40 @@
#pragma once
-extern "C" {
-#include <parc/security/parc_CryptoSuite.h>
-};
+#include <hicn/transport/auth/crypto_hash.h>
-#include <cstdint>
+extern "C" {
+#include <openssl/obj_mac.h>
+}
namespace transport {
namespace auth {
enum class CryptoSuite : uint8_t {
- RSA_SHA256 = PARCCryptoSuite_RSA_SHA256,
- DSA_SHA256 = PARCCryptoSuite_DSA_SHA256,
- RSA_SHA512 = PARCCryptoSuite_RSA_SHA512,
- HMAC_SHA256 = PARCCryptoSuite_HMAC_SHA256,
- HMAC_SHA512 = PARCCryptoSuite_HMAC_SHA512,
- NULL_CRC32C = PARCCryptoSuite_NULL_CRC32C,
- ECDSA_256K1 = PARCCryptoSuite_ECDSA_SHA256,
- UNKNOWN = PARCCryptoSuite_UNKNOWN
+ UNKNOWN,
+ ECDSA_BLAKE2B512,
+ ECDSA_BLAKE2S256,
+ ECDSA_SHA256,
+ ECDSA_SHA512,
+ RSA_BLAKE2B512,
+ RSA_BLAKE2S256,
+ RSA_SHA256,
+ RSA_SHA512,
+ HMAC_BLAKE2B512,
+ HMAC_BLAKE2S256,
+ HMAC_SHA256,
+ HMAC_SHA512,
+ DSA_BLAKE2B512,
+ DSA_BLAKE2S256,
+ DSA_SHA256,
+ DSA_SHA512,
};
+// Return the suite associated to the given NID
+CryptoSuite getSuite(int nid);
+
+// Return the hash type associated to the given suite
+CryptoHashType getHashType(CryptoSuite suite);
+
} // namespace auth
} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/identity.h b/libtransport/includes/hicn/transport/auth/identity.h
index 19157952e..be072f5d3 100644
--- a/libtransport/includes/hicn/transport/auth/identity.h
+++ b/libtransport/includes/hicn/transport/auth/identity.h
@@ -15,14 +15,17 @@
#pragma once
+#include <errno.h>
+#include <fcntl.h>
#include <hicn/transport/auth/signer.h>
+#include <unistd.h>
extern "C" {
-#include <parc/security/parc_Identity.h>
-#include <parc/security/parc_IdentityFile.h>
-#include <parc/security/parc_Pkcs12KeyStore.h>
-#include <parc/security/parc_Security.h>
-};
+#include <openssl/pkcs12.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+}
namespace transport {
namespace auth {
@@ -54,12 +57,20 @@ class Identity {
// Return the key store password.
std::string getPassword() const;
+ std::shared_ptr<X509> getCertificate() const;
+
+ std::shared_ptr<EVP_PKEY> getPrivateKey() const;
+
// Generate a new random identity.
static Identity generateIdentity(const std::string &subject_name = "");
private:
- PARCIdentity *identity_;
+ static void free_key(EVP_PKEY *T) { EVP_PKEY_free(T); }
+
+ std::string pwd_;
+ std::string filename_;
std::shared_ptr<AsymmetricSigner> signer_;
+ std::shared_ptr<X509> cert_;
};
} // namespace auth
diff --git a/libtransport/includes/hicn/transport/auth/signer.h b/libtransport/includes/hicn/transport/auth/signer.h
index fd5c4e6c6..405dd83cf 100644
--- a/libtransport/includes/hicn/transport/auth/signer.h
+++ b/libtransport/includes/hicn/transport/auth/signer.h
@@ -16,62 +16,79 @@
#pragma once
#include <hicn/transport/auth/common.h>
+#include <hicn/transport/auth/crypto_hash.h>
+#include <hicn/transport/auth/crypto_suite.h>
#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/utils/membuf.h>
extern "C" {
-#include <parc/security/parc_PublicKeySigner.h>
-#include <parc/security/parc_Security.h>
-#include <parc/security/parc_Signer.h>
-#include <parc/security/parc_SymmetricKeySigner.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
}
namespace transport {
namespace auth {
+class Identity;
class Signer {
// The base class from which all signer classes derive.
+ friend class Identity;
+
public:
Signer();
- Signer(PARCSigner *signer);
-
virtual ~Signer();
// Sign a packet.
virtual void signPacket(PacketPtr packet);
+ virtual void signBuffer(const std::vector<uint8_t> &buffer);
+ virtual void signBuffer(const utils::MemBuf *buffer);
+
+ // Return the signature.
+ std::vector<uint8_t> getSignature() const;
- // Set the signer object used to sign packets.
- void setSigner(PARCSigner *signer);
+ // Return the signature size in bytes.
+ virtual std::size_t getSignatureSize() const;
- // Return the signature size.
- size_t getSignatureSize() const;
+ // Return the field size necessary to hold the signature. The field size is
+ // always a multiple of 4. Use this function when allocating the signature
+ // packet header.
+ virtual std::size_t getSignatureFieldSize() const;
// Return the crypto suite associated to the signer.
- CryptoSuite getCryptoSuite() const;
+ CryptoSuite getSuite() const;
// Return the hash algorithm associated to the signer.
- CryptoHashType getCryptoHashType() const;
+ CryptoHashType getHashType() const;
- // Return the PARC signer.
- PARCSigner *getParcSigner() const;
+ protected:
+ CryptoSuite suite_;
+ std::vector<uint8_t> signature_;
+ std::size_t signature_len_;
+ std::shared_ptr<EVP_PKEY> key_;
+ CryptoHash key_id_;
+};
- // Return the PARC key store containing the signer key.
- PARCKeyStore *getParcKeyStore() const;
+class VoidSigner : public Signer {
+ // This class is the default socket signer. It does not sign packet.
+ public:
+ VoidSigner() = default;
- protected:
- PARCSigner *signer_;
- PARCKeyId *key_id_;
+ void signPacket(PacketPtr packet) override;
+ void signBuffer(const std::vector<uint8_t> &buffer) override;
+ void signBuffer(const utils::MemBuf *buffer) override;
};
class AsymmetricSigner : public Signer {
- // This class uses asymmetric verification to sign packets. The public key
- // must be given from a PARCKeyStore.
+ // This class uses asymmetric verification to sign packets.
public:
AsymmetricSigner() = default;
- AsymmetricSigner(PARCSigner *signer) : Signer(signer){};
// Construct an AsymmetricSigner from a key store and a given crypto suite.
- AsymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store);
+ AsymmetricSigner(CryptoSuite suite, std::shared_ptr<EVP_PKEY> key,
+ std::shared_ptr<EVP_PKEY> pub_key);
+
+ std::size_t getSignatureFieldSize() const override;
};
class SymmetricSigner : public Signer {
@@ -79,12 +96,8 @@ class SymmetricSigner : public Signer {
// key is derived from a passphrase.
public:
SymmetricSigner() = default;
- SymmetricSigner(PARCSigner *signer) : Signer(signer){};
-
- // Construct an SymmetricSigner from a key store and a given crypto suite.
- SymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store);
- // Construct an AsymmetricSigner from a passphrase and a given crypto suite.
+ // Construct a SymmetricSigner from a passphrase and a given crypto suite.
SymmetricSigner(CryptoSuite suite, const std::string &passphrase);
};
diff --git a/libtransport/includes/hicn/transport/auth/verifier.h b/libtransport/includes/hicn/transport/auth/verifier.h
index e6e561918..6321d4ed5 100644
--- a/libtransport/includes/hicn/transport/auth/verifier.h
+++ b/libtransport/includes/hicn/transport/auth/verifier.h
@@ -21,26 +21,26 @@
#include <hicn/transport/errors/errors.h>
#include <hicn/transport/interfaces/callbacks.h>
-#include <algorithm>
-
extern "C" {
-#include <parc/security/parc_CertificateFactory.h>
-#include <parc/security/parc_InMemoryVerifier.h>
-#include <parc/security/parc_Security.h>
-#include <parc/security/parc_SymmetricKeySigner.h>
-#include <parc/security/parc_Verifier.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
}
namespace transport {
namespace auth {
class Verifier {
- // The base class from which all verifier classes derive.
+ // The base Verifier class.
public:
- // The VerificationFailedCallback will be called by the transport if a data
- // packet (either a manifest or a content object) cannot be verified. The
- // application decides what to do then by returning a VerificationPolicy
- // object.
+ using SuffixMap = std::unordered_map<Suffix, CryptoHash>;
+ using PolicyMap = std::unordered_map<Suffix, VerificationPolicy>;
+
+ // The VerificationFailedCallback will be called by the transport if a
+ // data packet (either a manifest or a content object) was not validated.
+ // The application decides what to do then by returning a
+ // VerificationPolicy object.
using VerificationFailedCallback = std::function<auth::VerificationPolicy(
const core::ContentObject &content_object, std::error_code ec)>;
@@ -52,39 +52,41 @@ class Verifier {
virtual ~Verifier();
- // Verify a single packet and return whether or not the packet signature is
- // valid.
+ // Verify a single packet or buffer.
virtual bool verifyPacket(PacketPtr packet);
-
- // Verify a batch of packets. Return a vector with the same size as the packet
- // list, element i of that vector will contain the VerificationPolicy for
- // packet i.
- virtual std::vector<VerificationPolicy> verifyPackets(
- const std::vector<PacketPtr> &packets);
+ virtual bool verifyBuffer(const std::vector<uint8_t> &buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) = 0;
+ virtual bool verifyBuffer(const utils::MemBuf *buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) = 0;
+
+ // Verify a batch of packets. Return a mapping from packet suffixes to their
+ // VerificationPolicy.
+ virtual PolicyMap verifyPackets(const std::vector<PacketPtr> &packets);
VerificationPolicy verifyPackets(PacketPtr packet) {
- return verifyPackets(std::vector<PacketPtr>{packet}).front();
+ return verifyPackets(std::vector<PacketPtr>{packet})
+ .at(packet->getName().getSuffix());
}
+ // Verify that a set of packet hashes are present in another set of hashes
+ // that was extracted from manifests. Return a mapping from packet suffixes to
+ // their VerificationPolicy.
+ virtual PolicyMap verifyHashes(const SuffixMap &packet_map,
+ const SuffixMap &suffix_map);
+
// Verify that a batch of packets are valid using a map from packet suffixes
- // to hashes. A packet is considered valid if its hash correspond to the hash
- // present in the map. Return a vector with the same size as the packet list,
- // element i of that vector will contain the VerificationPolicy for packet i.
- virtual std::vector<VerificationPolicy> verifyPackets(
- const std::vector<PacketPtr> &packets,
- const std::unordered_map<Suffix, HashEntry> &suffix_map);
- VerificationPolicy verifyPackets(
- PacketPtr packet,
- const std::unordered_map<Suffix, HashEntry> &suffix_map) {
- return verifyPackets(std::vector<PacketPtr>{packet}, suffix_map).front();
+ // to hashes. A packet is considered valid if its hash is present in the map.
+ // Return a mapping from packet suffixes to their VerificationPolicy.
+ virtual PolicyMap verifyPackets(const std::vector<PacketPtr> &packets,
+ const SuffixMap &suffix_map);
+ VerificationPolicy verifyPackets(PacketPtr packet,
+ const SuffixMap &suffix_map) {
+ return verifyPackets(std::vector<PacketPtr>{packet}, suffix_map)
+ .at(packet->getName().getSuffix());
}
- // Add a general PARC key which can be used to verify packet signatures.
- void addKey(PARCKey *key);
-
- // Set the hasher object used to compute packet hashes.
- void setHasher(PARCCryptoHasher *hasher);
-
- // Set the callback for the case packet verification fails.
+ // Set the callback called when packet verification fails.
void setVerificationFailedCallback(
VerificationFailedCallback verification_failed_cb,
const std::vector<VerificationPolicy> &failed_policies =
@@ -94,50 +96,62 @@ class Verifier {
void getVerificationFailedCallback(
VerificationFailedCallback **verification_failed_cb);
- static size_t getSignatureSize(const PacketPtr);
-
protected:
- PARCCryptoHasher *hasher_;
- PARCVerifier *verifier_;
VerificationFailedCallback verification_failed_cb_;
std::vector<VerificationPolicy> failed_policies_;
- // Internally compute a packet hash using the hasher object.
- virtual CryptoHash computeHash(PacketPtr packet);
-
// Call VerificationFailedCallback if it is set and update the packet policy.
void callVerificationFailedCallback(PacketPtr packet,
VerificationPolicy &policy);
};
class VoidVerifier : public Verifier {
- // This class is the default socket verifier. It ignores completely the packet
- // signature and always returns true.
+ // This class is the default socket verifier. It ignores any packet signature
+ // and always returns true.
public:
bool verifyPacket(PacketPtr packet) override;
+ bool verifyBuffer(const std::vector<uint8_t> &buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) override;
+ bool verifyBuffer(const utils::MemBuf *buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) override;
- std::vector<VerificationPolicy> verifyPackets(
- const std::vector<PacketPtr> &packets) override;
+ PolicyMap verifyPackets(const std::vector<PacketPtr> &packets) override;
- std::vector<VerificationPolicy> verifyPackets(
- const std::vector<PacketPtr> &packets,
- const std::unordered_map<Suffix, HashEntry> &suffix_map) override;
+ PolicyMap verifyPackets(const std::vector<PacketPtr> &packets,
+ const SuffixMap &suffix_map) override;
};
class AsymmetricVerifier : public Verifier {
// This class uses asymmetric verification to validate packets. The public key
- // can be set directly or extracted from a certificate.
+ // can be directly set or extracted from a certificate.
public:
AsymmetricVerifier() = default;
- // Add a public key to the verifier.
- AsymmetricVerifier(PARCKey *pub_key);
+ // Construct an AsymmetricVerifier from an asymmetric key.
+ AsymmetricVerifier(std::shared_ptr<EVP_PKEY> key);
// Construct an AsymmetricVerifier from a certificate file.
AsymmetricVerifier(const std::string &cert_path);
+ AsymmetricVerifier(std::shared_ptr<X509> cert);
+
+ // Set the asymmetric key.
+ void setKey(std::shared_ptr<EVP_PKEY> key);
+
+ // Extract the public key from a certificate.
+ void useCertificate(const std::string &cert_path);
+ void useCertificate(std::shared_ptr<X509> cert);
- // Extract the public key of a certificate file.
- void setCertificate(const std::string &cert_path);
+ bool verifyBuffer(const std::vector<uint8_t> &buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) override;
+ bool verifyBuffer(const utils::MemBuf *buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) override;
+
+ private:
+ std::shared_ptr<EVP_PKEY> key_;
};
class SymmetricVerifier : public Verifier {
@@ -149,20 +163,18 @@ class SymmetricVerifier : public Verifier {
// Construct a SymmetricVerifier from a passphrase.
SymmetricVerifier(const std::string &passphrase);
- ~SymmetricVerifier();
-
// Create and set a symmetric key from a passphrase.
void setPassphrase(const std::string &passphrase);
- // Construct a signer object. Passphrase must be set beforehand.
- void setSigner(const PARCCryptoSuite &suite);
-
- virtual std::vector<VerificationPolicy> verifyPackets(
- const std::vector<PacketPtr> &packets) override;
+ bool verifyBuffer(const std::vector<uint8_t> &buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) override;
+ bool verifyBuffer(const utils::MemBuf *buffer,
+ const std::vector<uint8_t> &signature,
+ CryptoHashType hash_type) override;
protected:
- PARCBuffer *passphrase_;
- PARCSigner *signer_;
+ std::shared_ptr<EVP_PKEY> key_;
};
} // namespace auth
diff --git a/libtransport/includes/hicn/transport/core/CMakeLists.txt b/libtransport/includes/hicn/transport/core/CMakeLists.txt
index 2553b7dcd..14c795a7a 100644
--- a/libtransport/includes/hicn/transport/core/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/core/CMakeLists.txt
@@ -11,9 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/asio_wrapper.h
${CMAKE_CURRENT_SOURCE_DIR}/content_object.h
${CMAKE_CURRENT_SOURCE_DIR}/interest.h
${CMAKE_CURRENT_SOURCE_DIR}/name.h
diff --git a/libtransport/includes/hicn/transport/interfaces/verification_policy.h b/libtransport/includes/hicn/transport/core/asio_wrapper.h
index cb5140ac1..78cad35dc 100644
--- a/libtransport/includes/hicn/transport/interfaces/verification_policy.h
+++ b/libtransport/includes/hicn/transport/core/asio_wrapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -15,19 +15,14 @@
#pragma once
-#include <cstdint>
+#include <hicn/transport/portability/portability.h>
-namespace transport {
-namespace interface {
+TRANSPORT_PUSH_WARNING
+TRANSPORT_CLANG_DISABLE_WARNING("-Wdeprecated-declarations")
-/**
- * This policy allows the application to tell the transport what to do in case
- * the verification of a content object fails.
- */
-enum class VerificationPolicy : std::uint8_t {
- DROP_PACKET,
- ACCEPT_PACKET,
- ABORT_SESSION
-};
-} // namespace interface
-} // namespace transport \ No newline at end of file
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE
+#endif
+#include <asio.hpp>
+
+TRANSPORT_POP_WARNING
diff --git a/libtransport/includes/hicn/transport/core/connector_stats.h b/libtransport/includes/hicn/transport/core/connector_stats.h
index 1985331e9..fff370d02 100644
--- a/libtransport/includes/hicn/transport/core/connector_stats.h
+++ b/libtransport/includes/hicn/transport/core/connector_stats.h
@@ -1,5 +1,16 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#pragma once
diff --git a/libtransport/includes/hicn/transport/core/content_object.h b/libtransport/includes/hicn/transport/core/content_object.h
index 805bc814c..38baafc69 100644
--- a/libtransport/includes/hicn/transport/core/content_object.h
+++ b/libtransport/includes/hicn/transport/core/content_object.h
@@ -42,7 +42,7 @@ class ContentObject : public Packet {
std::size_t payload_size);
template <typename... Args>
- ContentObject(CopyBufferOp op, Args &&...args)
+ ContentObject(CopyBufferOp op, Args &&... args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
0) {
@@ -51,7 +51,7 @@ class ContentObject : public Packet {
}
template <typename... Args>
- ContentObject(WrapBufferOp op, Args &&...args)
+ ContentObject(WrapBufferOp op, Args &&... args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
0) {
@@ -60,7 +60,7 @@ class ContentObject : public Packet {
}
template <typename... Args>
- ContentObject(CreateOp op, Args &&...args)
+ ContentObject(CreateOp op, Args &&... args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
0) {
@@ -82,8 +82,6 @@ class ContentObject : public Packet {
void setName(const Name &name) override;
- void setName(Name &&name) override;
-
uint32_t getPathLabel() const;
ContentObject &setPathLabel(uint32_t path_label);
diff --git a/libtransport/includes/hicn/transport/core/endpoint.h b/libtransport/includes/hicn/transport/core/endpoint.h
index 4a19744a7..cb6b0f562 100644
--- a/libtransport/includes/hicn/transport/core/endpoint.h
+++ b/libtransport/includes/hicn/transport/core/endpoint.h
@@ -15,10 +15,7 @@
#pragma once
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio.hpp>
+#include <hicn/transport/core/asio_wrapper.h>
namespace transport {
diff --git a/libtransport/includes/hicn/transport/core/global_object_pool.h b/libtransport/includes/hicn/transport/core/global_object_pool.h
index e0b6e373f..d7f3a9e41 100644
--- a/libtransport/includes/hicn/transport/core/global_object_pool.h
+++ b/libtransport/includes/hicn/transport/core/global_object_pool.h
@@ -71,7 +71,7 @@ class PacketManager
template <
typename PacketType, typename... Args,
typename = std::enable_if_t<std::is_base_of<Packet, PacketType>::value>>
- typename PacketType::Ptr getPacket(Args &&...args) {
+ typename PacketType::Ptr getPacket(Args &&... args) {
PacketType *memory = nullptr;
memory = reinterpret_cast<PacketType *>(memory_pool_.allocateBlock());
@@ -98,7 +98,7 @@ class PacketManager
template <typename PacketType, typename... Args>
typename PacketType::Ptr getPacketFromExistingBuffer(uint8_t *buffer,
std::size_t length,
- Args &&...args) {
+ Args &&... args) {
auto offset = offsetof(PacketStorage, align);
auto memory = reinterpret_cast<PacketType *>(buffer - offset);
utils::STLAllocator<PacketType, MemoryPool> allocator(memory,
diff --git a/libtransport/includes/hicn/transport/core/interest.h b/libtransport/includes/hicn/transport/core/interest.h
index b41b0c94a..a5b9cf375 100644
--- a/libtransport/includes/hicn/transport/core/interest.h
+++ b/libtransport/includes/hicn/transport/core/interest.h
@@ -25,6 +25,8 @@ namespace transport {
namespace core {
+const uint32_t MAX_AGGREGATED_INTEREST = 128;
+
class Interest
: public Packet /*, public std::enable_shared_from_this<Interest>*/ {
private:
@@ -47,7 +49,7 @@ class Interest
Interest(MemBuf &&buffer);
template <typename... Args>
- Interest(CopyBufferOp op, Args &&...args)
+ Interest(CopyBufferOp op, Args &&... args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_interest_get_name(format_, packet_start_,
name_.getStructReference()) < 0) {
@@ -56,7 +58,7 @@ class Interest
}
template <typename... Args>
- Interest(WrapBufferOp op, Args &&...args)
+ Interest(WrapBufferOp op, Args &&... args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_interest_get_name(format_, packet_start_,
name_.getStructReference()) < 0) {
@@ -65,7 +67,7 @@ class Interest
}
template <typename... Args>
- Interest(CreateOp op, Args &&...args)
+ Interest(CreateOp op, Args &&... args)
: Packet(op, std::forward<Args>(args)...) {}
/* Move constructor */
@@ -85,8 +87,6 @@ class Interest
void setName(const Name &name) override;
- void setName(Name &&name) override;
-
void setLocator(const ip_address_t &ip_address) override;
ip_address_t getLocator() const override;
diff --git a/libtransport/includes/hicn/transport/core/io_module.h b/libtransport/includes/hicn/transport/core/io_module.h
index d4c3bb03a..ea3cf4e16 100644
--- a/libtransport/includes/hicn/transport/core/io_module.h
+++ b/libtransport/includes/hicn/transport/core/io_module.h
@@ -15,6 +15,7 @@
#pragma once
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/core/packet.h>
#include <hicn/transport/core/prefix.h>
@@ -24,11 +25,6 @@
#include <deque>
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio/io_service.hpp>
-
namespace transport {
namespace core {
diff --git a/libtransport/includes/hicn/transport/core/packet.h b/libtransport/includes/hicn/transport/core/packet.h
index 68daea841..269a1571a 100644
--- a/libtransport/includes/hicn/transport/core/packet.h
+++ b/libtransport/includes/hicn/transport/core/packet.h
@@ -15,19 +15,28 @@
#pragma once
+#include <hicn/transport/auth/crypto_hash.h>
+#include <hicn/transport/auth/crypto_suite.h>
+#include <hicn/transport/auth/key_id.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/core/payload_type.h>
#include <hicn/transport/errors/malformed_packet_exception.h>
#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/auth/crypto_hasher.h>
-#include <hicn/transport/auth/crypto_suite.h>
-#include <hicn/transport/auth/key_id.h>
#include <hicn/transport/utils/branch_prediction.h>
-#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/membuf.h>
#include <hicn/transport/utils/object_pool.h>
namespace transport {
+
+namespace auth {
+class Signer;
+class AsymmetricSigner;
+class SymmetricSigner;
+class Verifier;
+class AsymmetricVerifier;
+class SymmetricVerifier;
+} // namespace auth
+
namespace core {
/*
@@ -42,7 +51,11 @@ namespace core {
class Packet : public utils::MemBuf,
public std::enable_shared_from_this<Packet> {
friend class auth::Signer;
+ friend class auth::SymmetricSigner;
+ friend class auth::AsymmetricSigner;
friend class auth::Verifier;
+ friend class auth::AsymmetricVerifier;
+ friend class auth::SymmetricVerifier;
public:
using Ptr = std::shared_ptr<Packet>;
@@ -135,8 +148,6 @@ class Packet : public utils::MemBuf,
virtual void setName(const Name &name) = 0;
- virtual void setName(Name &&name) = 0;
-
virtual void setLifetime(uint32_t lifetime) = 0;
virtual uint32_t getLifetime() const = 0;
@@ -223,6 +234,7 @@ class Packet : public utils::MemBuf,
private:
virtual void resetForHash() = 0;
void setSignatureSize(std::size_t size_bytes);
+ void setSignatureSizeGap(std::size_t size_bytes);
void prependPayload(const uint8_t **buffer, std::size_t *size);
bool authenticationHeader() const { return _is_ah(format_); }
@@ -239,6 +251,22 @@ class Packet : public utils::MemBuf,
return size_bytes;
}
+ std::size_t getSignatureSizeGap() const {
+ uint8_t size_bytes;
+ int ret =
+ hicn_packet_get_signature_gap(format_, packet_start_, &size_bytes);
+
+ if (ret < 0) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ return (size_t)size_bytes;
+ }
+
+ std::size_t getSignatureSizeReal() const {
+ return getSignatureSize() - getSignatureSizeGap();
+ }
+
uint8_t *getSignature() const;
protected:
diff --git a/libtransport/includes/hicn/transport/errors/CMakeLists.txt b/libtransport/includes/hicn/transport/errors/CMakeLists.txt
index 5b04ace10..1d35c5b34 100644
--- a/libtransport/includes/hicn/transport/errors/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/errors/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/not_implemented_exception.h
${CMAKE_CURRENT_SOURCE_DIR}/invalid_ip_address_exception.h
diff --git a/libtransport/includes/hicn/transport/http/CMakeLists.txt b/libtransport/includes/hicn/transport/http/CMakeLists.txt
index 9cf618c21..9f4cdaf39 100644
--- a/libtransport/includes/hicn/transport/http/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/http/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/client_connection.h
${CMAKE_CURRENT_SOURCE_DIR}/request.h
diff --git a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
index 08f880930..40623dfe1 100644
--- a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/socket_consumer.h
${CMAKE_CURRENT_SOURCE_DIR}/socket_producer.h
diff --git a/libtransport/includes/hicn/transport/interfaces/callbacks.h b/libtransport/includes/hicn/transport/interfaces/callbacks.h
index 95b4d1977..22e111799 100644
--- a/libtransport/includes/hicn/transport/interfaces/callbacks.h
+++ b/libtransport/includes/hicn/transport/interfaces/callbacks.h
@@ -15,8 +15,8 @@
#pragma once
-#include <hicn/transport/interfaces/statistics.h>
#include <hicn/transport/auth/policies.h>
+#include <hicn/transport/interfaces/statistics.h>
#include <functional>
#include <system_error>
diff --git a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
index 7b284c520..d86744514 100644
--- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
+++ b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
@@ -15,8 +15,8 @@
#pragma once
-#include <hicn/transport/interfaces/socket_producer.h>
#include <hicn/transport/auth/identity.h>
+#include <hicn/transport/interfaces/socket_producer.h>
namespace transport {
diff --git a/libtransport/includes/hicn/transport/interfaces/portal.h b/libtransport/includes/hicn/transport/interfaces/portal.h
index 22c8591f4..66fc84256 100644
--- a/libtransport/includes/hicn/transport/interfaces/portal.h
+++ b/libtransport/includes/hicn/transport/interfaces/portal.h
@@ -15,14 +15,11 @@
#pragma once
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/core/prefix.h>
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio/io_service.hpp>
#include <functional>
#define UNSET_CALLBACK 0
@@ -71,7 +68,7 @@ class Portal {
class ConsumerCallback {
public:
virtual void onContentObject(core::Interest &i, core::ContentObject &c) = 0;
- virtual void onTimeout(core::Interest::Ptr &&i) = 0;
+ virtual void onTimeout(core::Interest::Ptr &i, const core::Name &n) = 0;
virtual void onError(std::error_code ec) = 0;
};
@@ -87,7 +84,8 @@ class Portal {
using OnContentObjectCallback =
std::function<void(core::Interest &, core::ContentObject &)>;
- using OnInterestTimeoutCallback = std::function<void(core::Interest::Ptr &&)>;
+ using OnInterestTimeoutCallback =
+ std::function<void(core::Interest::Ptr &, const core::Name &)>;
Portal();
@@ -202,4 +200,4 @@ class Portal {
};
} // namespace interface
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
index 621e7ce6f..5e0e81b9f 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
@@ -15,18 +15,14 @@
#pragma once
+#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/core/prefix.h>
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
-#include <hicn/transport/auth/verifier.h>
-
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio/io_service.hpp>
#define CONSUMER_FINISHED 0
#define CONSUMER_BUSY 1
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_producer.h b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
index 302b03f3f..27b603dfe 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_producer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
@@ -15,18 +15,14 @@
#pragma once
+#include <hicn/transport/auth/signer.h>
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/core/prefix.h>
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
-#include <hicn/transport/auth/signer.h>
-
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio/io_service.hpp>
namespace transport {
diff --git a/libtransport/includes/hicn/transport/interfaces/statistics.h b/libtransport/includes/hicn/transport/interfaces/statistics.h
index 92c58da23..1ff6f3edd 100644
--- a/libtransport/includes/hicn/transport/interfaces/statistics.h
+++ b/libtransport/includes/hicn/transport/interfaces/statistics.h
@@ -49,11 +49,13 @@ class TransportStatistics {
interest_FEC_tx_(0),
bytes_FEC_received_(0),
lost_data_(0),
+ definitely_lost_data_(0),
recovered_data_(0),
status_(-1),
// avg_data_rtt_(0),
avg_pending_pkt_(0.0),
- received_nacks_(0) {}
+ received_nacks_(0),
+ received_fec_(0) {}
TRANSPORT_ALWAYS_INLINE void updateRetxCount(uint64_t retx) {
retx_count_ += retx;
@@ -96,6 +98,10 @@ class TransportStatistics {
lost_data_ += pkt;
}
+ TRANSPORT_ALWAYS_INLINE void updateDefinitelyLostData(uint64_t pkt) {
+ definitely_lost_data_ += pkt;
+ }
+
TRANSPORT_ALWAYS_INLINE void updateRecoveredData(uint64_t bytes) {
recovered_data_ += bytes;
}
@@ -110,6 +116,10 @@ class TransportStatistics {
received_nacks_ += nacks;
}
+ TRANSPORT_ALWAYS_INLINE void updateReceivedFEC(uint32_t pkt) {
+ received_fec_ += pkt;
+ }
+
TRANSPORT_ALWAYS_INLINE uint64_t getRetxCount() const { return retx_count_; }
TRANSPORT_ALWAYS_INLINE uint64_t getBytesRecv() const {
@@ -142,6 +152,10 @@ class TransportStatistics {
TRANSPORT_ALWAYS_INLINE uint64_t getLostData() const { return lost_data_; }
+ TRANSPORT_ALWAYS_INLINE uint64_t getDefinitelyLostData() const {
+ return definitely_lost_data_;
+ }
+
TRANSPORT_ALWAYS_INLINE uint64_t getBytesRecoveredData() const {
return recovered_data_;
}
@@ -156,6 +170,10 @@ class TransportStatistics {
return received_nacks_;
}
+ TRANSPORT_ALWAYS_INLINE uint32_t getReceivedFEC() const {
+ return received_fec_;
+ }
+
TRANSPORT_ALWAYS_INLINE void setAlpha(double val) { alpha_ = val; }
TRANSPORT_ALWAYS_INLINE void reset() {
@@ -168,11 +186,13 @@ class TransportStatistics {
interest_FEC_tx_ = 0;
bytes_FEC_received_ = 0;
lost_data_ = 0;
+ definitely_lost_data_ = 0;
recovered_data_ = 0;
status_ = 0;
// avg_data_rtt_ = 0;
avg_pending_pkt_ = 0;
received_nacks_ = 0;
+ received_fec_ = 0;
}
private:
@@ -187,10 +207,12 @@ class TransportStatistics {
uint64_t interest_FEC_tx_;
uint64_t bytes_FEC_received_;
uint64_t lost_data_;
+ uint64_t definitely_lost_data_;
uint64_t recovered_data_;
int status_; // transport status (e.g. sync status, congestion etc.)
double avg_pending_pkt_;
uint32_t received_nacks_;
+ uint32_t received_fec_;
};
} // namespace interface
diff --git a/libtransport/includes/hicn/transport/portability/CMakeLists.txt b/libtransport/includes/hicn/transport/portability/CMakeLists.txt
index 469b11192..8094c0661 100644
--- a/libtransport/includes/hicn/transport/portability/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/portability/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/c_portability.h
${CMAKE_CURRENT_SOURCE_DIR}/portability.h
diff --git a/libtransport/includes/hicn/transport/portability/c_portability.h b/libtransport/includes/hicn/transport/portability/c_portability.h
index 9fe9ef90a..2675de000 100644
--- a/libtransport/includes/hicn/transport/portability/c_portability.h
+++ b/libtransport/includes/hicn/transport/portability/c_portability.h
@@ -34,3 +34,11 @@
#else
#define TRANSPORT_ALWAYS_INLINE inline
#endif
+
+// Unused
+#ifdef UNUSED
+#elif defined(__GNUC__) || defined(__clang__)
+#define UNUSED(x) (void)x
+#else
+#define UNUSED(x) x
+#endif
diff --git a/libtransport/includes/hicn/transport/portability/portability.h b/libtransport/includes/hicn/transport/portability/portability.h
index 539ce2d5a..24ef012f7 100644
--- a/libtransport/includes/hicn/transport/portability/portability.h
+++ b/libtransport/includes/hicn/transport/portability/portability.h
@@ -31,20 +31,41 @@ namespace portability {
constexpr bool little_endian_arch = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
constexpr bool big_endian_arch = !little_endian_arch;
-#if defined(__GNUC__)
-#define _TRANSPORT_GNU_DISABLE_WARNING(warning) #warning
-#define TRANSPORT_GNU_DISABLE_WARNING(warning) \
- _Pragma(_TRANSPORT_GNU_DISABLE_WARNING(GCC diagnostic ignored warning))
-
+// Generalize warning push/pop.
+#if defined(__GNUC__) || defined(__clang__)
+// Clang & GCC
+#define TRANSPORT_PUSH_WARNING _Pragma("GCC diagnostic push")
+#define TRANSPORT_POP_WARNING _Pragma("GCC diagnostic pop")
+#define TRANSPORT_GNU_DISABLE_WARNING_INTERNAL2(warningName) #warningName
+#define TRANSPORT_GNU_DISABLE_WARNING(warningName) \
+ _Pragma(TRANSPORT_GNU_DISABLE_WARNING_INTERNAL2( \
+ GCC diagnostic ignored warningName))
#ifdef __clang__
-#define TRANSPORT_CLANG_DISABLE_WARNING(warning) \
- TRANSPORT_GNU_DISABLE_WARNING(warning)
-#define TRANSPORT_GCC_DISABLE_WARNING(warning)
+#define TRANSPORT_CLANG_DISABLE_WARNING(warningName) \
+ TRANSPORT_GNU_DISABLE_WARNING(warningName)
+#define TRANSPORT_GCC_DISABLE_WARNING(warningName)
#else
-#define TRANSPORT_CLANG_DISABLE_WARNING(warning)
-#define TRANSPORT_GCC_DISABLE_WARNING(warning) \
- TRANSPORT_GNU_DISABLE_WARNING(warning)
+#define TRANSPORT_CLANG_DISABLE_WARNING(warningName)
+#define TRANSPORT_GCC_DISABLE_WARNING(warningName) \
+ TRANSPORT_GNU_DISABLE_WARNING(warningName)
#endif
+#define TRANSPORT_MSVC_DISABLE_WARNING(warningNumber)
+#elif defined(_MSC_VER)
+#define TRANSPORT_PUSH_WARNING __pragma(warning(push))
+#define TRANSPORT_POP_WARNING __pragma(warning(pop))
+// Disable the GCC warnings.
+#define TRANSPORT_GNU_DISABLE_WARNING(warningName)
+#define TRANSPORT_GCC_DISABLE_WARNING(warningName)
+#define TRANSPORT_CLANG_DISABLE_WARNING(warningName)
+#define TRANSPORT_MSVC_DISABLE_WARNING(warningNumber) \
+ __pragma(warning(disable : warningNumber))
+#else
+#define TRANSPORT_PUSH_WARNING
+#define TRANSPORT_POP_WARNING
+#define TRANSPORT_GNU_DISABLE_WARNING(warningName)
+#define TRANSPORT_GCC_DISABLE_WARNING(warningName)
+#define TRANSPORT_CLANG_DISABLE_WARNING(warningName)
+#define TRANSPORT_MSVC_DISABLE_WARNING(warningNumber)
#endif
} // namespace portability
diff --git a/libtransport/includes/hicn/transport/portability/win_portability.h b/libtransport/includes/hicn/transport/portability/win_portability.h
index 246b734ad..24c7a932a 100644
--- a/libtransport/includes/hicn/transport/portability/win_portability.h
+++ b/libtransport/includes/hicn/transport/portability/win_portability.h
@@ -22,7 +22,6 @@
#endif
#include <fcntl.h>
#include <io.h>
-#include <parc/windows/parc_Utils.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
diff --git a/libtransport/includes/hicn/transport/security/CMakeLists.txt b/libtransport/includes/hicn/transport/security/CMakeLists.txt
deleted file mode 100644
index 58a96780b..000000000
--- a/libtransport/includes/hicn/transport/security/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/signer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/verifier.h
- ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hasher.h
- ${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.h
- ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.h
- ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash_type.h
- ${CMAKE_CURRENT_SOURCE_DIR}/identity.h
- ${CMAKE_CURRENT_SOURCE_DIR}/key_id.h
-)
-
-set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/security/crypto_hash.h b/libtransport/includes/hicn/transport/security/crypto_hash.h
deleted file mode 100644
index 5a58f258b..000000000
--- a/libtransport/includes/hicn/transport/security/crypto_hash.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/errors/runtime_exception.h>
-#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/security/crypto_hash_type.h>
-#include <hicn/transport/utils/array.h>
-
-extern "C" {
-#include <parc/security/parc_CryptoHash.h>
-};
-
-#include <cstring>
-#include <unordered_map>
-
-namespace utils {
-
-class CryptoHasher;
-
-struct EnumClassHash {
- template <typename T>
- std::size_t operator()(T t) const {
- return static_cast<std::size_t>(t);
- }
-};
-
-static std::unordered_map<CryptoHashType, std::size_t, EnumClassHash>
- hash_size_map = {{CryptoHashType::SHA_256, 32},
- {CryptoHashType::CRC32C, 4},
- {CryptoHashType::SHA_512, 64}};
-
-class Signer;
-class Verifier;
-
-class CryptoHash {
- friend class CryptoHasher;
- friend class Signer;
- friend class Verifier;
-
- public:
- CryptoHash() : hash_(nullptr) {}
-
- CryptoHash(const CryptoHash& other) {
- if (other.hash_) {
- hash_ = parcCryptoHash_Acquire(other.hash_);
- }
- }
-
- CryptoHash(CryptoHash&& other) {
- if (other.hash_) {
- hash_ = parcCryptoHash_Acquire(other.hash_);
- }
- }
-
- template <typename T>
- CryptoHash(const T* buffer, std::size_t length, CryptoHashType hash_type) {
- hash_ = parcCryptoHash_CreateFromArray(
- static_cast<PARCCryptoHashType>(hash_type), buffer, length);
- }
-
- ~CryptoHash() {
- if (hash_) {
- parcCryptoHash_Release(&hash_);
- }
- }
-
- CryptoHash& operator=(const CryptoHash& other) {
- if (other.hash_) {
- hash_ = parcCryptoHash_Acquire(other.hash_);
- }
-
- return *this;
- }
-
- template <typename T>
- utils::Array<T> getDigest() const {
- return utils::Array<T>(
- static_cast<T*>(parcBuffer_Overlay(parcCryptoHash_GetDigest(hash_), 0)),
- parcBuffer_Remaining(parcCryptoHash_GetDigest(hash_)));
- }
-
- CryptoHashType getType() {
- return static_cast<CryptoHashType>(parcCryptoHash_GetDigestType(hash_));
- }
-
- template <typename T>
- static bool compareBinaryDigest(const T* digest1, const T* digest2,
- CryptoHashType hash_type) {
- if (hash_size_map.find(hash_type) == hash_size_map.end()) {
- return false;
- }
-
- return !static_cast<bool>(
- std::memcmp(digest1, digest2, hash_size_map[hash_type]));
- }
-
- TRANSPORT_ALWAYS_INLINE void display() {
- parcBuffer_Display(parcCryptoHash_GetDigest(hash_), 2);
- }
-
- private:
- PARCCryptoHash* hash_;
-};
-
-} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/security/crypto_hasher.h b/libtransport/includes/hicn/transport/security/crypto_hasher.h
deleted file mode 100644
index 9367c3bc8..000000000
--- a/libtransport/includes/hicn/transport/security/crypto_hasher.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/security/crypto_hash.h>
-
-extern "C" {
-#include <parc/security/parc_CryptoHasher.h>
-};
-
-namespace utils {
-
-class CryptoHasher {
- public:
- CryptoHasher(CryptoHashType hash_type)
- : hasher_(parcCryptoHasher_Create(
- static_cast<PARCCryptoHashType>(hash_type))),
- managed_(true) {}
-
- CryptoHasher(PARCCryptoHasher* hasher) : hasher_(hasher), managed_(false) {}
-
- ~CryptoHasher() {
- if (managed_) {
- parcCryptoHasher_Release(&hasher_);
- }
- }
-
- CryptoHasher& init() {
- if (parcCryptoHasher_Init(hasher_) == -1) {
- throw errors::RuntimeException("Cryptohash init failed.");
- }
-
- return *this;
- }
-
- template <typename T>
- CryptoHasher& updateBytes(const T* buffer, std::size_t length) {
- if (parcCryptoHasher_UpdateBytes(hasher_, buffer, length) == -1) {
- throw errors::RuntimeException("Cryptohash updateBytes failed.");
- }
- return *this;
- }
-
- CryptoHash finalize() {
- CryptoHash hash;
- hash.hash_ = parcCryptoHasher_Finalize(hasher_);
- return hash;
- }
-
- private:
- PARCCryptoHasher* hasher_;
- bool managed_;
-};
-
-} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/security/crypto_suite.h b/libtransport/includes/hicn/transport/security/crypto_suite.h
deleted file mode 100644
index 017938f8f..000000000
--- a/libtransport/includes/hicn/transport/security/crypto_suite.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-extern "C" {
-#include <parc/security/parc_CryptoSuite.h>
-};
-
-#include <cstdint>
-
-namespace utils {
-
-enum class CryptoSuite : uint8_t {
- RSA_SHA256 = PARCCryptoSuite_RSA_SHA256,
- DSA_SHA256 = PARCCryptoSuite_DSA_SHA256,
- RSA_SHA512 = PARCCryptoSuite_RSA_SHA512,
- HMAC_SHA256 = PARCCryptoSuite_HMAC_SHA256,
- HMAC_SHA512 = PARCCryptoSuite_HMAC_SHA512,
- NULL_CRC32C = PARCCryptoSuite_NULL_CRC32C,
- ECDSA_256K1 = PARCCryptoSuite_ECDSA_SHA256,
- UNKNOWN = PARCCryptoSuite_UNKNOWN
-};
-}
diff --git a/libtransport/includes/hicn/transport/security/identity.h b/libtransport/includes/hicn/transport/security/identity.h
deleted file mode 100644
index a575af134..000000000
--- a/libtransport/includes/hicn/transport/security/identity.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/security/crypto_suite.h>
-#include <hicn/transport/security/signer.h>
-
-extern "C" {
-#include <parc/security/parc_Identity.h>
-#include <parc/security/parc_IdentityFile.h>
-#include <parc/security/parc_Pkcs12KeyStore.h>
-};
-
-#include <string>
-
-namespace utils {
-
-class Identity {
- public:
- Identity(const std::string &keystore_name,
- const std::string &keystore_password, CryptoSuite suite,
- unsigned int signature_length, unsigned int validity_days,
- const std::string &subject_name);
-
- Identity(const Identity &other);
-
- Identity(std::string &file_name, std::string &password,
- utils::CryptoHashType hash_algorithm);
-
- ~Identity();
-
- static Identity generateIdentity(const std::string &subject_name);
-
- std::string getFileName();
-
- std::string getPassword();
-
- std::shared_ptr<Signer> getSigner();
-
- size_t getSignatureLength() const;
-
- private:
- PARCIdentity *identity_;
- std::shared_ptr<Signer> signer_;
- utils::CryptoHashType hash_algorithm_;
-};
-
-} // namespace utils
diff --git a/libtransport/includes/hicn/transport/security/signer.h b/libtransport/includes/hicn/transport/security/signer.h
deleted file mode 100644
index 45bcdb516..000000000
--- a/libtransport/includes/hicn/transport/security/signer.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/core/packet.h>
-
-extern "C" {
-#include <parc/security/parc_CryptoHashType.h>
-#include <parc/security/parc_CryptoSuite.h>
-#include <parc/security/parc_KeyStore.h>
-#include <parc/security/parc_Signer.h>
-#include <parc/security/parc_SymmetricKeySigner.h>
-}
-
-namespace utils {
-
-using Packet = transport::core::Packet;
-
-/**
- * A signer can use a single key (asymmetric or symmetric) to sign a packet.
- */
-class Signer {
- friend class Identity;
-
- public:
- /**
- * Create a Signer
- *
- * @param keyStore A keystore containing a private key or simmetric key to
- * use to sign packet with this Signer.
- * @param suite CryptoSuite to use to verify the signature
- */
- Signer(PARCKeyStore *keyStore, CryptoSuite suite);
-
- /**
- * Create a Signer
- *
- * @param passphrase A string from which the symmetric key will be derived
- * @param suite CryptoSuite to use to verify the signature
- */
- Signer(const std::string &passphrase, CryptoSuite suite);
-
- Signer(const PARCSigner *signer, CryptoSuite suite);
-
- Signer(const PARCSigner *signer);
-
- ~Signer();
-
- /**
- * @brief Sign a packet
- *
- * This method is general and must be used for Public-private key signature,
- * HMAC and CRC.
- *
- * @param packet A pointer to the header of the packet to sign. Mutable
- * field in the packet must be set to 0.
- * @param key_id Indentifier of the key to use to generate the signature.
- */
- void sign(Packet &packet);
-
- size_t getSignatureLength();
-
- PARCKeyStore *getKeyStore();
-
- private:
- CryptoSuite suite_;
- PARCSigner *signer_ = nullptr;
- PARCKeyId *key_id_ = nullptr;
- size_t signature_length_;
-};
-
-} // namespace utils
diff --git a/libtransport/includes/hicn/transport/security/verifier.h b/libtransport/includes/hicn/transport/security/verifier.h
deleted file mode 100644
index 838868427..000000000
--- a/libtransport/includes/hicn/transport/security/verifier.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/core/packet.h>
-
-extern "C" {
-#include <parc/security/parc_CertificateFactory.h>
-#include <parc/security/parc_InMemoryVerifier.h>
-#include <parc/security/parc_KeyId.h>
-#include <parc/security/parc_Security.h>
-#include <parc/security/parc_SymmetricKeySigner.h>
-#include <parc/security/parc_Verifier.h>
-}
-
-namespace utils {
-
-using Packet = transport::core::Packet;
-
-/**
- * A verifier holds a crypto cache that contains all the keys to use for
- * verify signatures/hmacs.
- */
-class Verifier {
- public:
- Verifier();
-
- ~Verifier();
-
- /**
- * @brief Check if a key is already in this Verifier.
- *
- * A PARCVerifier contains a CryptoCache with a set of key to use for
- * verification purposes.
- *
- * @param keyId Identifier of the key to match in the CryptoCache of the
- * Verifier.
- * @return true if the key is found, false otherwise.
- */
- bool hasKey(PARCKeyId *keyId);
-
- /**
- * @brief Add a key to this Verifier
- *
- * @param key to add
- * @return true if the key was added successfully, false otherwise.
- */
- bool addKey(PARCKey *key);
-
- PARCKeyId *addKeyFromPassphrase(const std::string &passphrase,
- CryptoSuite suite);
-
- PARCKeyId *addKeyFromCertificate(const std::string &file_name);
-
- /**
- * @brief Verify a Signature
- *
- * This method is general and must be used for Public-private key signature,
- * HMAC and CRC.
- *
- * @param signature A pointer to the buffer holding the signature
- * @param sign_len Lenght of the signature (must be consistent with the type
- * of the key)
- * @param bufferSigned A pointer to the packet header signed with
- * signature. Mutable fields and the signature field in the packet must be
- * set to 0
- * @param buf_len Lenght of bufferSigned
- * @param suite CryptoSuite to use to verify the signature
- * @param key_id Indentifier of the key to use to verify the signature. The
- * key must be already present in the Verifier.
- */
- int verify(const Packet &packet);
-
- CryptoHash getPacketHash(const Packet &packet, CryptoHasher &hasher);
-
- private:
- PARCVerifier *verifier_ = nullptr;
- PARCSigner *signer_ = nullptr;
-};
-
-} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/CMakeLists.txt b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
index 7094601f4..75f727f03 100644
--- a/libtransport/includes/hicn/transport/utils/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/array.h
${CMAKE_CURRENT_SOURCE_DIR}/string_tokenizer.h
diff --git a/libtransport/includes/hicn/transport/utils/event_thread.h b/libtransport/includes/hicn/transport/utils/event_thread.h
index bb6ab90ef..15ec1d62c 100644
--- a/libtransport/includes/hicn/transport/utils/event_thread.h
+++ b/libtransport/includes/hicn/transport/utils/event_thread.h
@@ -16,13 +16,9 @@
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/errors/runtime_exception.h>
-#include <hicn/transport/utils/log.h>
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio.hpp>
#include <memory>
#include <thread>
diff --git a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
index b1df36493..298b6f9d1 100644
--- a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
+++ b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
@@ -35,7 +35,6 @@ class FixedBlockAllocator
if (!p_block) {
if (TRANSPORT_EXPECT_FALSE(current_pool_index_ >= max_objects_)) {
// Allocate new memory block
- TRANSPORT_LOGV("Allocating new block of %zu size", SIZE * OBJECTS);
p_pools_.emplace_front(
new typename std::aligned_storage<SIZE>::type[max_objects_]);
// reset current_pool_index_
@@ -151,10 +150,7 @@ class STLAllocator {
using value_type = T;
STLAllocator(pointer memory, Pool* memory_pool)
- : memory_(memory), pool_(memory_pool) {
- TRANSPORT_LOGV("Creating allocator. This: %p, memory: %p, memory_pool: %p",
- this, memory, memory_pool);
- }
+ : memory_(memory), pool_(memory_pool) {}
~STLAllocator() {}
@@ -173,28 +169,17 @@ class STLAllocator {
const_pointer address(const_reference x) const { return &x; }
pointer allocate(size_type n, pointer hint = 0) {
- TRANSPORT_LOGV(
- "Allocating memory (%zu). This: %p, memory: %p, memory_pool: %p", n,
- this, memory_, pool_);
return static_cast<pointer>(memory_);
}
- void deallocate(pointer p, size_type n) {
- TRANSPORT_LOGV("Deallocating memory. This: %p, memory: %p, memory_pool: %p",
- this, memory_, pool_);
- pool_->deallocateBlock(memory_);
- }
+ void deallocate(pointer p, size_type n) { pool_->deallocateBlock(memory_); }
template <typename... Args>
void construct(pointer p, Args&&... args) {
new (static_cast<pointer>(p)) T(std::forward<Args>(args)...);
}
- void destroy(pointer p) {
- TRANSPORT_LOGV("Destroying object. This: %p, memory: %p, memory_pool: %p",
- this, memory_, pool_);
- p->~T();
- }
+ void destroy(pointer p) { p->~T(); }
private:
void* memory_;
diff --git a/libtransport/includes/hicn/transport/utils/linux.h b/libtransport/includes/hicn/transport/utils/linux.h
index 105196fd2..4fbf5f01e 100644
--- a/libtransport/includes/hicn/transport/utils/linux.h
+++ b/libtransport/includes/hicn/transport/utils/linux.h
@@ -19,7 +19,6 @@
#include <arpa/inet.h>
#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/utils/log.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <stdio.h>
@@ -49,7 +48,6 @@ static TRANSPORT_ALWAYS_INLINE int retrieveInterfaceAddress(
*address = *(struct sockaddr_in6 *)ifa->ifa_addr;
getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), addr,
sizeof(addr), NULL, 0, NI_NUMERICHOST);
- TRANSPORT_LOGI("Interface: %s\tAddress: %s", ifa->ifa_name, addr);
}
}
}
diff --git a/libtransport/includes/hicn/transport/utils/log.h b/libtransport/includes/hicn/transport/utils/log.h
index 3c4f1277a..0947b755e 100644
--- a/libtransport/includes/hicn/transport/utils/log.h
+++ b/libtransport/includes/hicn/transport/utils/log.h
@@ -13,1045 +13,35 @@
* limitations under the License.
*/
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2017 wonder-mice
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
#pragma once
-/* To detect incompatible changes you can define TRANSPORT_LOG_VERSION_REQUIRED
- * to be the current value of TRANSPORT_LOG_VERSION before including this file
- * (or via compiler command line):
- *
- * #define TRANSPORT_LOG_VERSION_REQUIRED 4
- * #include <hicn/transport_log.h>
- *
- * Compilation will fail when included file has different version.
- */
-#define TRANSPORT_LOG_VERSION 4
-#if defined(TRANSPORT_LOG_VERSION_REQUIRED)
-#if TRANSPORT_LOG_VERSION_REQUIRED != TRANSPORT_LOG_VERSION
-#error different transport_log version required
-#endif
-#endif
-
-/* Log level guideline:
- * - TRANSPORT_LOG_FATAL - happened something impossible and absolutely
- * unexpected. Process can't continue and must be terminated. Example: division
- * by zero, unexpected modifications from other thread.
- * - TRANSPORT_LOG_ERROR - happened something possible, but highly unexpected.
- * The process is able to recover and continue execution. Example: out of memory
- * (could also be FATAL if not handled properly).
- * - TRANSPORT_LOG_WARN - happened something that *usually* should not happen
- * and significantly changes application behavior for some period of time.
- * Example: configuration file not found, auth error.
- * - TRANSPORT_LOG_INFO - happened significant life cycle event or major state
- * transition.
- * Example: app started, user logged in.
- * - TRANSPORT_LOG_DEBUG - minimal set of events that could help to reconstruct
- * the execution path. Usually disabled in release builds.
- * - TRANSPORT_LOG_VERBOSE - all other events. Usually disabled in release
- * builds.
- *
- * *Ideally*, log file of debugged, well tested, production ready application
- * should be empty or very small. Choosing a right log level is as important as
- * providing short and self descriptive log message.
- */
-#define TRANSPORT_LOG_VERBOSE 1
-#define TRANSPORT_LOG_DEBUG 2
-#define TRANSPORT_LOG_INFO 3
-#define TRANSPORT_LOG_WARN 4
-#define TRANSPORT_LOG_ERROR 5
-#define TRANSPORT_LOG_FATAL 6
-#define TRANSPORT_LOG_NONE 0xFF
-
-/* "Current" log level is a compile time check and has no runtime overhead. Log
- * level that is below current log level it said to be "disabled". Otherwise,
- * it's "enabled". Log messages that are disabled has no runtime overhead - they
- * are converted to no-op by preprocessor and then eliminated by compiler.
- * Current log level is configured per compilation module (.c/.cpp/.m file) by
- * defining TRANSPORT_LOG_DEF_LEVEL or TRANSPORT_LOG_LEVEL. TRANSPORT_LOG_LEVEL
- * has higer priority and when defined overrides value provided by
- * TRANSPORT_LOG_DEF_LEVEL.
- *
- * Common practice is to define default current log level with
- * TRANSPORT_LOG_DEF_LEVEL in build script (e.g. Makefile, CMakeLists.txt, gyp,
- * etc.) for the entire project or target:
- *
- * CC_ARGS := -DTRANSPORT_LOG_DEF_LEVEL=TRANSPORT_LOG_INFO
- *
- * And when necessary to override it with TRANSPORT_LOG_LEVEL in .c/.cpp/.m
- * files before including transport_log.h:
- *
- * #define TRANSPORT_LOG_LEVEL TRANSPORT_LOG_VERBOSE
- * #include <hicn/transport_log.h>
- *
- * If both TRANSPORT_LOG_DEF_LEVEL and TRANSPORT_LOG_LEVEL are undefined, then
- * TRANSPORT_LOG_INFO will be used for release builds (NDEBUG is defined) and
- * TRANSPORT_LOG_DEBUG otherwise (NDEBUG is not defined).
- */
-#if defined(TRANSPORT_LOG_LEVEL)
-#define _TRANSPORT_LOG_LEVEL TRANSPORT_LOG_LEVEL
-#elif defined(TRANSPORT_LOG_DEF_LEVEL)
-#define _TRANSPORT_LOG_LEVEL TRANSPORT_LOG_DEF_LEVEL
-#else
-#ifdef NDEBUG
-#define _TRANSPORT_LOG_LEVEL TRANSPORT_LOG_INFO
-#else
-#define _TRANSPORT_LOG_LEVEL TRANSPORT_LOG_DEBUG
-#endif
-#endif
-
-/* "Output" log level is a runtime check. When log level is below output log
- * level it said to be "turned off" (or just "off" for short). Otherwise it's
- * "turned on" (or just "on"). Log levels that were "disabled" (see
- * TRANSPORT_LOG_LEVEL and TRANSPORT_LOG_DEF_LEVEL) can't be "turned on", but
- * "enabled" log levels could be "turned off". Only messages with log level
- * which is "turned on" will reach output facility. All other messages will be
- * ignored (and their arguments will not be evaluated). Output log level is a
- * global property and configured per process using
- * transport_log_set_output_level() function which can be called at any time.
- *
- * Though in some cases it could be useful to configure output log level per
- * compilation module or per library. There are two ways to achieve that:
- * - Define TRANSPORT_LOG_OUTPUT_LEVEL to expresion that evaluates to desired
- * output log level.
- * - Copy transport_log.h and transport_log.c files into your library and build
- * it with TRANSPORT_LOG_LIBRARY_PREFIX defined to library specific prefix. See
- * TRANSPORT_LOG_LIBRARY_PREFIX for more details.
- *
- * When defined, TRANSPORT_LOG_OUTPUT_LEVEL must evaluate to integral value that
- * corresponds to desired output log level. Use it only when compilation module
- * is required to have output log level which is different from global output
- * log level set by transport_log_set_output_level() function. For other cases,
- * consider defining TRANSPORT_LOG_LEVEL or using
- * transport_log_set_output_level() function.
- *
- * Example:
- *
- * #define TRANSPORT_LOG_OUTPUT_LEVEL g_module_log_level
- * #include <hicn/transport_log.h>
- * static int g_module_log_level = TRANSPORT_LOG_INFO;
- * static void foo() {
- * TRANSPORT_LOGI("Will check g_module_log_level for output log level");
- * }
- * void debug_log(bool on) {
- * g_module_log_level = on? TRANSPORT_LOG_DEBUG: TRANSPORT_LOG_INFO;
- * }
- *
- * Note on performance. This expression will be evaluated each time message is
- * logged (except when message log level is "disabled" - see TRANSPORT_LOG_LEVEL
- * for details). Keep this expression as simple as possible, otherwise it will
- * not only add runtime overhead, but also will increase size of call site
- * (which will result in larger executable). The prefered way is to use integer
- * variable (as in example above). If structure must be used, log_level field
- * must be the first field in this structure:
- *
- * #define TRANSPORT_LOG_OUTPUT_LEVEL (g_config.log_level)
- * #include <hicn/transport_log.h>
- * struct config {
- * int log_level;
- * unsigned other_field;
- * [...]
- * };
- * static config g_config = {TRANSPORT_LOG_INFO, 0, ...};
- *
- * This allows compiler to generate more compact load instruction (no need to
- * specify offset since it's zero). Calling a function to get output log level
- * is generaly a bad idea, since it will increase call site size and runtime
- * overhead even further.
- */
-#if defined(TRANSPORT_LOG_OUTPUT_LEVEL)
-#define _TRANSPORT_LOG_OUTPUT_LEVEL TRANSPORT_LOG_OUTPUT_LEVEL
-#else
-#define _TRANSPORT_LOG_OUTPUT_LEVEL _transport_log_global_output_lvl
-#endif
-
-/* "Tag" is a compound string that could be associated with a log message. It
- * consists of tag prefix and tag (both are optional).
- *
- * Tag prefix is a global property and configured per process using
- * transport_log_set_tag_prefix() function. Tag prefix identifies context in
- * which component or module is running (e.g. process name). For example, the
- * same library could be used in both client and server processes that work on
- * the same machine. Tag prefix could be used to easily distinguish between
- * them. For more details about tag prefix see transport_log_set_tag_prefix()
- * function. Tag prefix
- *
- * Tag identifies component or module. It is configured per compilation module
- * (.c/.cpp/.m file) by defining TRANSPORT_LOG_TAG or TRANSPORT_LOG_DEF_TAG.
- * TRANSPORT_LOG_TAG has higer priority and when defined overrides value
- * provided by TRANSPORT_LOG_DEF_TAG. When defined, value must evaluate to
- * (const char *), so for strings double quotes must be used.
- *
- * Default tag could be defined with TRANSPORT_LOG_DEF_TAG in build script (e.g.
- * Makefile, CMakeLists.txt, gyp, etc.) for the entire project or target:
- *
- * CC_ARGS := -DTRANSPORT_LOG_DEF_TAG=\"MISC\"
- *
- * And when necessary could be overriden with TRANSPORT_LOG_TAG in .c/.cpp/.m
- * files before including transport_log.h:
- *
- * #define TRANSPORT_LOG_TAG "MAIN"
- * #include <hicn/transport_log.h>
- *
- * If both TRANSPORT_LOG_DEF_TAG and TRANSPORT_LOG_TAG are undefined no tag will
- * be added to the log message (tag prefix still could be added though).
- *
- * Output example:
- *
- * 04-29 22:43:20.244 40059 1299 I hello.MAIN Number of arguments: 1
- * | |
- * | +- tag (e.g. module)
- * +- tag prefix (e.g. process name)
- */
-#if defined(TRANSPORT_LOG_TAG)
-#define _TRANSPORT_LOG_TAG TRANSPORT_LOG_TAG
-#elif defined(TRANSPORT_LOG_DEF_TAG)
-#define _TRANSPORT_LOG_TAG TRANSPORT_LOG_DEF_TAG
-#else
-#define _TRANSPORT_LOG_TAG 0
-#endif
-
-/* Source location is part of a log line that describes location (function or
- * method name, file name and line number, e.g. "runloop@main.cpp:68") of a
- * log statement that produced it.
- * Source location formats are:
- * - TRANSPORT_LOG_SRCLOC_NONE - don't add source location to log line.
- * - TRANSPORT_LOG_SRCLOC_SHORT - add source location in short form (file and
- * line number, e.g. "@main.cpp:68").
- * - TRANSPORT_LOG_SRCLOC_LONG - add source location in long form (function or
- * method name, file and line number, e.g. "runloop@main.cpp:68").
- */
-#define TRANSPORT_LOG_SRCLOC_NONE 0
-#define TRANSPORT_LOG_SRCLOC_SHORT 1
-#define TRANSPORT_LOG_SRCLOC_LONG 2
-
-/* Source location format is configured per compilation module (.c/.cpp/.m
- * file) by defining TRANSPORT_LOG_DEF_SRCLOC or TRANSPORT_LOG_SRCLOC.
- * TRANSPORT_LOG_SRCLOC has higer priority and when defined overrides value
- * provided by TRANSPORT_LOG_DEF_SRCLOC.
- *
- * Common practice is to define default format with TRANSPORT_LOG_DEF_SRCLOC in
- * build script (e.g. Makefile, CMakeLists.txt, gyp, etc.) for the entire
- * project or target:
- *
- * CC_ARGS := -DTRANSPORT_LOG_DEF_SRCLOC=TRANSPORT_LOG_SRCLOC_LONG
- *
- * And when necessary to override it with TRANSPORT_LOG_SRCLOC in .c/.cpp/.m
- * files before including transport_log.h:
- *
- * #define TRANSPORT_LOG_SRCLOC TRANSPORT_LOG_SRCLOC_NONE
- * #include <hicn/transport_log.h>
- *
- * If both TRANSPORT_LOG_DEF_SRCLOC and TRANSPORT_LOG_SRCLOC are undefined, then
- * TRANSPORT_LOG_SRCLOC_NONE will be used for release builds (NDEBUG is defined)
- * and TRANSPORT_LOG_SRCLOC_LONG otherwise (NDEBUG is not defined).
- */
-#if defined(TRANSPORT_LOG_SRCLOC)
-#define _TRANSPORT_LOG_SRCLOC TRANSPORT_LOG_SRCLOC
-#elif defined(TRANSPORT_LOG_DEF_SRCLOC)
-#define _TRANSPORT_LOG_SRCLOC TRANSPORT_LOG_DEF_SRCLOC
-#else
-#ifdef NDEBUG
-#define _TRANSPORT_LOG_SRCLOC TRANSPORT_LOG_SRCLOC_NONE
-#else
-#define _TRANSPORT_LOG_SRCLOC TRANSPORT_LOG_SRCLOC_LONG
-#endif
-#endif
-#if TRANSPORT_LOG_SRCLOC_LONG == _TRANSPORT_LOG_SRCLOC
-#define _TRANSPORT_LOG_SRCLOC_FUNCTION _TRANSPORT_LOG_FUNCTION
-#else
-#define _TRANSPORT_LOG_SRCLOC_FUNCTION 0
-#endif
-
-/* Censoring provides conditional logging of secret information, also known as
- * Personally Identifiable Information (PII) or Sensitive Personal Information
- * (SPI). Censoring can be either enabled (TRANSPORT_LOG_CENSORED) or disabled
- * (TRANSPORT_LOG_UNCENSORED). When censoring is enabled, log statements marked
- * as "secrets" will be ignored and will have zero overhead (arguments also will
- * not be evaluated).
- */
-#define TRANSPORT_LOG_CENSORED 1
-#define TRANSPORT_LOG_UNCENSORED 0
-
-/* Censoring is configured per compilation module (.c/.cpp/.m file) by defining
- * TRANSPORT_LOG_DEF_CENSORING or TRANSPORT_LOG_CENSORING.
- * TRANSPORT_LOG_CENSORING has higer priority and when defined overrides value
- * provided by TRANSPORT_LOG_DEF_CENSORING.
- *
- * Common practice is to define default censoring with
- * TRANSPORT_LOG_DEF_CENSORING in build script (e.g. Makefile, CMakeLists.txt,
- * gyp, etc.) for the entire project or target:
- *
- * CC_ARGS := -DTRANSPORT_LOG_DEF_CENSORING=TRANSPORT_LOG_CENSORED
- *
- * And when necessary to override it with TRANSPORT_LOG_CENSORING in .c/.cpp/.m
- * files before including transport_log.h (consider doing it only for debug
- * purposes and be very careful not to push such temporary changes to source
- * control):
- *
- * #define TRANSPORT_LOG_CENSORING TRANSPORT_LOG_UNCENSORED
- * #include <hicn/transport_log.h>
- *
- * If both TRANSPORT_LOG_DEF_CENSORING and TRANSPORT_LOG_CENSORING are
- * undefined, then TRANSPORT_LOG_CENSORED will be used for release builds
- * (NDEBUG is defined) and TRANSPORT_LOG_UNCENSORED otherwise (NDEBUG is not
- * defined).
- */
-#if defined(TRANSPORT_LOG_CENSORING)
-#define _TRANSPORT_LOG_CENSORING TRANSPORT_LOG_CENSORING
-#elif defined(TRANSPORT_LOG_DEF_CENSORING)
-#define _TRANSPORT_LOG_CENSORING TRANSPORT_LOG_DEF_CENSORING
-#else
-#ifdef NDEBUG
-#define _TRANSPORT_LOG_CENSORING TRANSPORT_LOG_CENSORED
-#else
-#define _TRANSPORT_LOG_CENSORING TRANSPORT_LOG_UNCENSORED
-#endif
-#endif
-
-/* Check censoring at compile time. Evaluates to true when censoring is disabled
- * (i.e. when secrets will be logged). For example:
- *
- * #if TRANSPORT_LOG_SECRETS
- * char ssn[16];
- * getSocialSecurityNumber(ssn);
- * TRANSPORT_LOGI("Customer ssn: %s", ssn);
- * #endif
- *
- * See TRANSPORT_LOG_SECRET() macro for a more convenient way of guarding single
- * log statement.
- */
-#define TRANSPORT_LOG_SECRETS \
- (TRANSPORT_LOG_UNCENSORED == _TRANSPORT_LOG_CENSORING)
-
-/* Static (compile-time) initialization support allows to configure logging
- * before entering main() function. This mostly useful in C++ where functions
- * and methods could be called during initialization of global objects. Those
- * functions and methods could record log messages too and for that reason
- * static initialization of logging configuration is customizable.
- *
- * Macros below allow to specify values to use for initial configuration:
- * - TRANSPORT_LOG_EXTERN_TAG_PREFIX - tag prefix (default: none)
- * - TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT - global format options (default: see
- * TRANSPORT_LOG_MEM_WIDTH in transport_log.c)
- * - TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT - global output facility (default:
- * stderr or platform specific, see TRANSPORT_LOG_USE_XXX macros in
- * transport_log.c)
- * - TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL - global output log level
- * (default: 0 - all levals are "turned on")
- *
- * For example, in log_config.c:
- *
- * #include <hicn/transport_log.h>
- * TRANSPORT_LOG_DEFINE_TAG_PREFIX = "MyApp";
- * TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT = {CUSTOM_MEM_WIDTH};
- * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {TRANSPORT_LOG_PUT_STD,
- * custom_output_callback, 0}; TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL =
- * TRANSPORT_LOG_INFO;
- *
- * However, to use any of those macros transport_log library must be compiled
- * with following macros defined:
- * - to use TRANSPORT_LOG_DEFINE_TAG_PREFIX define
- * TRANSPORT_LOG_EXTERN_TAG_PREFIX
- * - to use TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT define
- * TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT
- * - to use TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT define
- * TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT
- * - to use TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL define
- * TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
- *
- * When transport_log library compiled with one of TRANSPORT_LOG_EXTERN_XXX
- * macros defined, corresponding TRANSPORT_LOG_DEFINE_XXX macro MUST be used
- * exactly once somewhere. Otherwise build will fail with link error (undefined
- * symbol).
- */
-#define TRANSPORT_LOG_DEFINE_TAG_PREFIX const char *_transport_log_tag_prefix
-#define TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT \
- transport_log_format _transport_log_global_format
-#define TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT \
- transport_log_output _transport_log_global_output
-#define TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL \
- int _transport_log_global_output_lvl
-
-/* Pointer to global format options. Direct modification is not allowed. Use
- * transport_log_set_mem_width() instead. Could be used to initialize
- * transport_log_spec structure:
- *
- * const transport_log_output g_output = {TRANSPORT_LOG_PUT_STD,
- * output_callback, 0}; const transport_log_spec g_spec =
- * {TRANSPORT_LOG_GLOBAL_FORMAT, &g_output}; TRANSPORT_LOGI_AUX(&g_spec,
- * "Hello");
- */
-#define TRANSPORT_LOG_GLOBAL_FORMAT \
- ((const transport_log_format *)&_transport_log_global_format)
-
-/* Pointer to global output variable. Direct modification is not allowed. Use
- * transport_log_set_output_v() or transport_log_set_output_p() instead. Could
- * be used to initialize transport_log_spec structure:
- *
- * const transport_log_format g_format = {40};
- * const transport_log_spec g_spec = {g_format, TRANSPORT_LOG_GLOBAL_OUTPUT};
- * TRANSPORT_LOGI_AUX(&g_spec, "Hello");
- */
-#define TRANSPORT_LOG_GLOBAL_OUTPUT \
- ((const transport_log_output *)&_transport_log_global_output)
-
-/* When defined, all library symbols produced by linker will be prefixed with
- * provided value. That allows to use transport_log library privately in another
- * libraries without exposing transport_log symbols in their original form (to
- * avoid possible conflicts with other libraries / components that also could
- * use transport_log for logging). Value must be without quotes, for example:
- *
- * CC_ARGS := -DTRANSPORT_LOG_LIBRARY_PREFIX=my_lib_
- *
- * Note, that in this mode TRANSPORT_LOG_LIBRARY_PREFIX must be defined when
- * building transport_log library AND it also must be defined to the same value
- * when building a library that uses it. For example, consider fictional
- * KittyHttp library that wants to use transport_log for logging. First approach
- * that could be taken is to add transport_log.h and transport_log.c to the
- * KittyHttp's source code tree directly. In that case it will be enough just to
- * define TRANSPORT_LOG_LIBRARY_PREFIX in KittyHttp's build script:
- *
- * // KittyHttp/CMakeLists.txt
- * target_compile_definitions(KittyHttp PRIVATE
- * "TRANSPORT_LOG_LIBRARY_PREFIX=KittyHttp_")
- *
- * If KittyHttp doesn't want to include transport_log source code in its source
- * tree and wants to build transport_log as a separate library than
- * transport_log library must be built with TRANSPORT_LOG_LIBRARY_PREFIX defined
- * to KittyHttp_ AND KittyHttp library itself also needs to define
- * TRANSPORT_LOG_LIBRARY_PREFIX to KittyHttp_. It can do so either in its build
- * script, as in example above, or by providing a wrapper header that KittyHttp
- * library will need to use instead of transport_log.h:
- *
- * // KittyHttpLogging.h
- * #define TRANSPORT_LOG_LIBRARY_PREFIX KittyHttp_
- * #include <hicn/transport_log.h>
- *
- * Regardless of the method chosen, the end result is that transport_log symbols
- * will be prefixed with "KittyHttp_", so if a user of KittyHttp (say
- * DogeBrowser) also uses transport_log for logging, they will not interferer
- * with each other. Both will have their own log level, output facility, format
- * options etc.
- */
-#ifdef TRANSPORT_LOG_LIBRARY_PREFIX
-#define _TRANSPORT_LOG_DECOR__(prefix, name) prefix##name
-#define _TRANSPORT_LOG_DECOR_(prefix, name) _TRANSPORT_LOG_DECOR__(prefix, name)
-#define _TRANSPORT_LOG_DECOR(name) \
- _TRANSPORT_LOG_DECOR_(TRANSPORT_LOG_LIBRARY_PREFIX, name)
-
-#define transport_log_set_tag_prefix \
- _TRANSPORT_LOG_DECOR(transport_log_set_tag_prefix)
-#define transport_log_set_mem_width \
- _TRANSPORT_LOG_DECOR(transport_log_set_mem_width)
-#define transport_log_set_output_level \
- _TRANSPORT_LOG_DECOR(transport_log_set_output_level)
-#define transport_log_set_output_v \
- _TRANSPORT_LOG_DECOR(transport_log_set_output_v)
-#define transport_log_set_output_p \
- _TRANSPORT_LOG_DECOR(transport_log_set_output_p)
-#define transport_log_out_stderr_callback \
- _TRANSPORT_LOG_DECOR(transport_log_out_stderr_callback)
-#define _transport_log_tag_prefix \
- _TRANSPORT_LOG_DECOR(_transport_log_tag_prefix)
-#define _transport_log_global_format \
- _TRANSPORT_LOG_DECOR(_transport_log_global_format)
-#define _transport_log_global_output \
- _TRANSPORT_LOG_DECOR(_transport_log_global_output)
-#define _transport_log_global_output_lvl \
- _TRANSPORT_LOG_DECOR(_transport_log_global_output_lvl)
-#define _transport_log_write_d _TRANSPORT_LOG_DECOR(_transport_log_write_d)
-#define _transport_log_write_aux_d \
- _TRANSPORT_LOG_DECOR(_transport_log_write_aux_d)
-#define _transport_log_write _TRANSPORT_LOG_DECOR(_transport_log_write)
-#define _transport_log_write_aux _TRANSPORT_LOG_DECOR(_transport_log_write_aux)
-#define _transport_log_write_mem_d \
- _TRANSPORT_LOG_DECOR(_transport_log_write_mem_d)
-#define _transport_log_write_mem_aux_d \
- _TRANSPORT_LOG_DECOR(_transport_log_write_mem_aux_d)
-#define _transport_log_write_mem _TRANSPORT_LOG_DECOR(_transport_log_write_mem)
-#define _transport_log_write_mem_aux \
- _TRANSPORT_LOG_DECOR(_transport_log_write_mem_aux)
-#define _transport_log_stderr_spec \
- _TRANSPORT_LOG_DECOR(_transport_log_stderr_spec)
-#endif
-
-#if defined(__printflike)
-#define _TRANSPORT_LOG_PRINTFLIKE(str_index, first_to_check) \
- __printflike(str_index, first_to_check)
-#elif defined(__GNUC__)
-#define _TRANSPORT_LOG_PRINTFLIKE(str_index, first_to_check) \
- __attribute__((format(__printf__, str_index, first_to_check)))
-#else
-#define _TRANSPORT_LOG_PRINTFLIKE(str_index, first_to_check)
-#endif
-
-#if (defined(_WIN32) || defined(_WIN64)) && !defined(__GNUC__)
-#define _TRANSPORT_LOG_FUNCTION __FUNCTION__
-#else
-#define _TRANSPORT_LOG_FUNCTION __func__
-#endif
-
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
-#define _TRANSPORT_LOG_INLINE __inline
-#define _TRANSPORT_LOG_IF(cond) \
- __pragma(warning(push)) __pragma(warning(disable : 4127)) if (cond) \
- __pragma(warning(pop))
-#define _TRANSPORT_LOG_WHILE(cond) \
- __pragma(warning(push)) __pragma(warning(disable : 4127)) while (cond) \
- __pragma(warning(pop))
-#else
-#define _TRANSPORT_LOG_INLINE inline
-#define _TRANSPORT_LOG_IF(cond) if (cond)
-#define _TRANSPORT_LOG_WHILE(cond) while (cond)
-#endif
-#define _TRANSPORT_LOG_NEVER _TRANSPORT_LOG_IF(0)
-#define _TRANSPORT_LOG_ONCE _TRANSPORT_LOG_WHILE(0)
+#include <hicn/transport/utils/singleton.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <ostream>
-/* Set tag prefix. Prefix will be separated from the tag with dot ('.').
- * Use 0 or empty string to disable (default). Common use is to set it to
- * the process (or build target) name (e.g. to separate client and server
- * processes). Function will NOT copy provided prefix string, but will store the
- * pointer. Hence specified prefix string must remain valid. See
- * TRANSPORT_LOG_DEFINE_TAG_PREFIX for a way to set it before entering main()
- * function. See TRANSPORT_LOG_TAG for more information about tag and tag
- * prefix.
- */
-void transport_log_set_tag_prefix(const char *const prefix);
-
-/* Set number of bytes per log line in memory (ASCII-HEX) output. Example:
- *
- * I hello.MAIN 4c6f72656d20697073756d20646f6c6f Lorem ipsum dolo
- * |<- w bytes ->| |<- w chars ->|
- *
- * See TRANSPORT_LOGF_MEM and TRANSPORT_LOGF_MEM_AUX for more details.
- */
-void transport_log_set_mem_width(const unsigned w);
+#define foreach_log_level \
+ _(Info, LOG(INFO)) \
+ _(Warning, LOG(WARNING)) \
+ _(Error, LOG(ERROR)) \
+ _(Fatal, LOG(FATAL))
-/* Set "output" log level. See TRANSPORT_LOG_LEVEL and
- * TRANSPORT_LOG_OUTPUT_LEVEL for more info about log levels.
- */
-void transport_log_set_output_level(const int lvl);
+#define CLASS_NAME(log_level) Log##log_level
-/* Put mask is a set of flags that define what fields will be added to each
- * log message. Default value is TRANSPORT_LOG_PUT_STD and other flags could be
- * used to alter its behavior. See transport_log_set_output_v() for more
- * details.
- *
- * Note about TRANSPORT_LOG_PUT_SRC: it will be added only in debug builds
- * (NDEBUG is not defined).
- */
-enum {
- TRANSPORT_LOG_PUT_CTX = 1 << 0, /* context (time, pid, tid, log level) */
- TRANSPORT_LOG_PUT_TAG = 1 << 1, /* tag (including tag prefix) */
- TRANSPORT_LOG_PUT_SRC = 1 << 2, /* source location (file, line, function) */
- TRANSPORT_LOG_PUT_MSG = 1 << 3, /* message text (formatted string) */
- TRANSPORT_LOG_PUT_STD = 0xffff, /* everything (default) */
-};
+namespace utils {
-typedef struct transport_log_message {
- int lvl; /* Log level of the message */
- const char *tag; /* Associated tag (without tag prefix) */
- char *buf; /* Buffer start */
- char *e; /* Buffer end (last position where EOL with 0 could be written) */
- char *p; /* Buffer content end (append position) */
- char *tag_b; /* Prefixed tag start */
- char *tag_e; /* Prefixed tag end (if != tag_b, points to msg separator) */
- char *msg_b; /* Message start (expanded format string) */
-} transport_log_message;
-
-/* Type of output callback function. It will be called for each log line allowed
- * by both "current" and "output" log levels ("enabled" and "turned on").
- * Callback function is allowed to modify content of the buffers pointed by the
- * msg, but it's not allowed to modify any of msg fields. Buffer pointed by msg
- * is UTF-8 encoded (no BOM mark).
- */
-typedef void (*transport_log_output_cb)(const transport_log_message *msg,
- void *arg);
-
-/* Format options. For more details see transport_log_set_mem_width().
- */
-typedef struct transport_log_format {
- unsigned mem_width; /* Bytes per line in memory (ASCII-HEX) dump */
-} transport_log_format;
-
-/* Output facility.
- */
-typedef struct transport_log_output {
- unsigned
- mask; /* What to put into log line buffer (see TRANSPORT_LOG_PUT_XXX) */
- void *arg; /* User provided output callback argument */
- transport_log_output_cb callback; /* Output callback function */
-} transport_log_output;
-
-/* Set output callback function.
- *
- * Mask allows to control what information will be added to the log line buffer
- * before callback function is invoked. Default mask value is
- * TRANSPORT_LOG_PUT_STD.
- */
-void transport_log_set_output_v(const unsigned mask, void *const arg,
- const transport_log_output_cb callback);
-static _TRANSPORT_LOG_INLINE void transport_log_set_output_p(
- const transport_log_output *const output) {
- transport_log_set_output_v(output->mask, output->arg, output->callback);
-}
-
-/* Used with _AUX macros and allows to override global format and output
- * facility. Use TRANSPORT_LOG_GLOBAL_FORMAT and TRANSPORT_LOG_GLOBAL_OUTPUT for
- * values from global configuration. Example:
- *
- * static const transport_log_output module_output = {
- * TRANSPORT_LOG_PUT_STD, 0, custom_output_callback
- * };
- * static const transport_log_spec module_spec = {
- * TRANSPORT_LOG_GLOBAL_FORMAT, &module_output
- * };
- * TRANSPORT_LOGI_AUX(&module_spec, "Position: %ix%i", x, y);
- *
- * See TRANSPORT_LOGF_AUX and TRANSPORT_LOGF_MEM_AUX for details.
- */
-typedef struct transport_log_spec {
- const transport_log_format *format;
- const transport_log_output *output;
-} transport_log_spec;
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Execute log statement if condition is true. Example:
- *
- * TRANSPORT_LOG_IF(1 < 2, TRANSPORT_LOGI("Log this"));
- * TRANSPORT_LOG_IF(1 > 2, TRANSPORT_LOGI("Don't log this"));
- *
- * Keep in mind though, that if condition can't be evaluated at compile time,
- * then it will be evaluated at run time. This will increase exectuable size
- * and can have noticeable performance overhead. Try to limit conditions to
- * expressions that can be evaluated at compile time.
- */
-#define TRANSPORT_LOG_IF(cond, f) \
- do { \
- _TRANSPORT_LOG_IF((cond)) { f; } \
- } \
- _TRANSPORT_LOG_ONCE
-
-/* Mark log statement as "secret". Log statements that are marked as secrets
- * will NOT be executed when censoring is enabled (see TRANSPORT_LOG_CENSORED).
- * Example:
- *
- * TRANSPORT_LOG_SECRET(TRANSPORT_LOGI("Credit card: %s", credit_card));
- * TRANSPORT_LOG_SECRET(TRANSPORT_LOGD_MEM(cipher, cipher_sz, "Cipher
- * bytes:"));
- */
-#define TRANSPORT_LOG_SECRET(f) TRANSPORT_LOG_IF(TRANSPORT_LOG_SECRETS, f)
+#define _(class_name, macro_name) \
+ class CLASS_NAME(class_name) : public Singleton<CLASS_NAME(class_name)> { \
+ friend class Singleton<CLASS_NAME(class_name)>; \
+ \
+ public: \
+ std::ostream& getStream(); \
+ };
+foreach_log_level
+#undef _
-/* Check "current" log level at compile time (ignoring "output" log level).
- * Evaluates to true when specified log level is enabled. For example:
- *
- * #if TRANSPORT_LOG_ENABLED_DEBUG
- * const char *const g_enum_strings[] = {
- * "enum_value_0", "enum_value_1", "enum_value_2"
- * };
- * #endif
- * // ...
- * #if TRANSPORT_LOG_ENABLED_DEBUG
- * TRANSPORT_LOGD("enum value: %s", g_enum_strings[v]);
- * #endif
- *
- * See TRANSPORT_LOG_LEVEL for details.
- */
-#define TRANSPORT_LOG_ENABLED(lvl) ((lvl) >= _TRANSPORT_LOG_LEVEL)
-#define TRANSPORT_LOG_ENABLED_VERBOSE \
- TRANSPORT_LOG_ENABLED(TRANSPORT_LOG_VERBOSE)
-#define TRANSPORT_LOG_ENABLED_DEBUG TRANSPORT_LOG_ENABLED(TRANSPORT_LOG_DEBUG)
-#define TRANSPORT_LOG_ENABLED_INFO TRANSPORT_LOG_ENABLED(TRANSPORT_LOG_INFO)
-#define TRANSPORT_LOG_ENABLED_WARN TRANSPORT_LOG_ENABLED(TRANSPORT_LOG_WARN)
-#define TRANSPORT_LOG_ENABLED_ERROR TRANSPORT_LOG_ENABLED(TRANSPORT_LOG_ERROR)
-#define TRANSPORT_LOG_ENABLED_FATAL TRANSPORT_LOG_ENABLED(TRANSPORT_LOG_FATAL)
-
-/* Check "output" log level at run time (taking into account "current" log
- * level as well). Evaluates to true when specified log level is turned on AND
- * enabled. For example:
- *
- * if (TRANSPORT_LOG_ON_DEBUG)
- * {
- * char hash[65];
- * sha256(data_ptr, data_sz, hash);
- * TRANSPORT_LOGD("data: len=%u, sha256=%s", data_sz, hash);
- * }
- *
- * See TRANSPORT_LOG_OUTPUT_LEVEL for details.
- */
-#define TRANSPORT_LOG_ON(lvl) \
- (TRANSPORT_LOG_ENABLED((lvl)) && (lvl) >= _TRANSPORT_LOG_OUTPUT_LEVEL)
-#define TRANSPORT_LOG_ON_VERBOSE TRANSPORT_LOG_ON(TRANSPORT_LOG_VERBOSE)
-#define TRANSPORT_LOG_ON_DEBUG TRANSPORT_LOG_ON(TRANSPORT_LOG_DEBUG)
-#define TRANSPORT_LOG_ON_INFO TRANSPORT_LOG_ON(TRANSPORT_LOG_INFO)
-#define TRANSPORT_LOG_ON_WARN TRANSPORT_LOG_ON(TRANSPORT_LOG_WARN)
-#define TRANSPORT_LOG_ON_ERROR TRANSPORT_LOG_ON(TRANSPORT_LOG_ERROR)
-#define TRANSPORT_LOG_ON_FATAL TRANSPORT_LOG_ON(TRANSPORT_LOG_FATAL)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern const char *_transport_log_tag_prefix;
-extern transport_log_format _transport_log_global_format;
-extern transport_log_output _transport_log_global_output;
-extern int _transport_log_global_output_lvl;
-extern const transport_log_spec _transport_log_stderr_spec;
-
-void _transport_log_write_d(const char *const func, const char *const file,
- const unsigned line, const int lvl,
- const char *const tag, const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(6, 7);
-void _transport_log_write_aux_d(const char *const func, const char *const file,
- const unsigned line,
- const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(7, 8);
-void _transport_log_write(const int lvl, const char *const tag,
- const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(3, 4);
-void _transport_log_write_aux(const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(4, 5);
-void _transport_log_write_mem_d(const char *const func, const char *const file,
- const unsigned line, const int lvl,
- const char *const tag, const void *const d,
- const unsigned d_sz, const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(8, 9);
-void _transport_log_write_mem_aux_d(const char *const func,
- const char *const file, const unsigned line,
- const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(9, 10);
-void _transport_log_write_mem(const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(5, 6);
-void _transport_log_write_mem_aux(const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...)
- _TRANSPORT_LOG_PRINTFLIKE(6, 7);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Message logging macros:
- * - TRANSPORT_LOGV("format string", args, ...)
- * - TRANSPORT_LOGD("format string", args, ...)
- * - TRANSPORT_LOGI("format string", args, ...)
- * - TRANSPORT_LOGW("format string", args, ...)
- * - TRANSPORT_LOGE("format string", args, ...)
- * - TRANSPORT_LOGF("format string", args, ...)
- *
- * Memory logging macros:
- * - TRANSPORT_LOGV_MEM(data_ptr, data_sz, "format string", args, ...)
- * - TRANSPORT_LOGD_MEM(data_ptr, data_sz, "format string", args, ...)
- * - TRANSPORT_LOGI_MEM(data_ptr, data_sz, "format string", args, ...)
- * - TRANSPORT_LOGW_MEM(data_ptr, data_sz, "format string", args, ...)
- * - TRANSPORT_LOGE_MEM(data_ptr, data_sz, "format string", args, ...)
- * - TRANSPORT_LOGF_MEM(data_ptr, data_sz, "format string", args, ...)
- *
- * Auxiliary logging macros:
- * - TRANSPORT_LOGV_AUX(&log_instance, "format string", args, ...)
- * - TRANSPORT_LOGD_AUX(&log_instance, "format string", args, ...)
- * - TRANSPORT_LOGI_AUX(&log_instance, "format string", args, ...)
- * - TRANSPORT_LOGW_AUX(&log_instance, "format string", args, ...)
- * - TRANSPORT_LOGE_AUX(&log_instance, "format string", args, ...)
- * - TRANSPORT_LOGF_AUX(&log_instance, "format string", args, ...)
- *
- * Auxiliary memory logging macros:
- * - TRANSPORT_LOGV_MEM_AUX(&log_instance, data_ptr, data_sz, "format string",
- * args, ...)
- * - TRANSPORT_LOGD_MEM_AUX(&log_instance, data_ptr, data_sz, "format string",
- * args, ...)
- * - TRANSPORT_LOGI_MEM_AUX(&log_instance, data_ptr, data_sz, "format string",
- * args, ...)
- * - TRANSPORT_LOGW_MEM_AUX(&log_instance, data_ptr, data_sz, "format string",
- * args, ...)
- * - TRANSPORT_LOGE_MEM_AUX(&log_instance, data_ptr, data_sz, "format string",
- * args, ...)
- * - TRANSPORT_LOGF_MEM_AUX(&log_instance, data_ptr, data_sz, "format string",
- * args, ...)
- *
- * Preformatted string logging macros:
- * - TRANSPORT_LOGV_STR("preformatted string");
- * - TRANSPORT_LOGD_STR("preformatted string");
- * - TRANSPORT_LOGI_STR("preformatted string");
- * - TRANSPORT_LOGW_STR("preformatted string");
- * - TRANSPORT_LOGE_STR("preformatted string");
- * - TRANSPORT_LOGF_STR("preformatted string");
- *
- * Explicit log level and tag macros:
- * - TRANSPORT_LOG_WRITE(level, tag, "format string", args, ...)
- * - TRANSPORT_LOG_WRITE_MEM(level, tag, data_ptr, data_sz, "format string",
- * args, ...)
- * - TRANSPORT_LOG_WRITE_AUX(&log_instance, level, tag, "format string", args,
- * ...)
- * - TRANSPORT_LOG_WRITE_MEM_AUX(&log_instance, level, tag, data_ptr, data_sz,
- * "format string", args, ...)
- *
- * Format string follows printf() conventions. Both data_ptr and data_sz could
- * be 0. Tag can be 0 as well. Most compilers will verify that type of arguments
- * match format specifiers in format string.
- *
- * Library assuming UTF-8 encoding for all strings (char *), including format
- * string itself.
- */
-#if TRANSPORT_LOG_SRCLOC_NONE == _TRANSPORT_LOG_SRCLOC
-#define TRANSPORT_LOG_WRITE(lvl, tag, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) _transport_log_write(lvl, tag, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#define TRANSPORT_LOG_WRITE_MEM(lvl, tag, d, d_sz, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) \
- _transport_log_write_mem(lvl, tag, d, d_sz, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#define TRANSPORT_LOG_WRITE_AUX(log, lvl, tag, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) \
- _transport_log_write_aux(log, lvl, tag, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#define TRANSPORT_LOG_WRITE_MEM_AUX(log, lvl, tag, d, d_sz, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) \
- _transport_log_write_mem_aux(log, lvl, tag, d, d_sz, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#else
-#define TRANSPORT_LOG_WRITE(lvl, tag, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) \
- _transport_log_write_d(_TRANSPORT_LOG_SRCLOC_FUNCTION, __FILE__, \
- __LINE__, lvl, tag, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#define TRANSPORT_LOG_WRITE_MEM(lvl, tag, d, d_sz, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) \
- _transport_log_write_mem_d(_TRANSPORT_LOG_SRCLOC_FUNCTION, __FILE__, \
- __LINE__, lvl, tag, d, d_sz, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#define TRANSPORT_LOG_WRITE_AUX(log, lvl, tag, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) \
- _transport_log_write_aux_d(_TRANSPORT_LOG_SRCLOC_FUNCTION, __FILE__, \
- __LINE__, log, lvl, tag, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#define TRANSPORT_LOG_WRITE_MEM_AUX(log, lvl, tag, d, d_sz, ...) \
- do { \
- if (TRANSPORT_LOG_ON(lvl)) \
- _transport_log_write_mem_aux_d(_TRANSPORT_LOG_SRCLOC_FUNCTION, __FILE__, \
- __LINE__, log, lvl, tag, d, d_sz, \
- __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-#endif
-
-static _TRANSPORT_LOG_INLINE void _transport_log_unused(const int dummy, ...) {
- (void)dummy;
-}
-
-#define _TRANSPORT_LOG_UNUSED(...) \
- do { \
- _TRANSPORT_LOG_NEVER _transport_log_unused(0, __VA_ARGS__); \
- } \
- _TRANSPORT_LOG_ONCE
-
-#if TRANSPORT_LOG_ENABLED_VERBOSE
-#define TRANSPORT_LOGV(...) \
- TRANSPORT_LOG_WRITE(TRANSPORT_LOG_VERBOSE, _TRANSPORT_LOG_TAG, __VA_ARGS__)
-#define TRANSPORT_LOGV_AUX(log, ...) \
- TRANSPORT_LOG_WRITE_AUX(log, TRANSPORT_LOG_VERBOSE, _TRANSPORT_LOG_TAG, \
- __VA_ARGS__)
-#define TRANSPORT_LOGV_MEM(d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM(TRANSPORT_LOG_VERBOSE, _TRANSPORT_LOG_TAG, d, d_sz, \
- __VA_ARGS__)
-#define TRANSPORT_LOGV_MEM_AUX(log, d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM(log, TRANSPORT_LOG_VERBOSE, _TRANSPORT_LOG_TAG, d, \
- d_sz, __VA_ARGS__)
-#else
-#define TRANSPORT_LOGV(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGV_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGV_MEM(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGV_MEM_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
-#if TRANSPORT_LOG_ENABLED_DEBUG
-#define TRANSPORT_LOGD(...) \
- TRANSPORT_LOG_WRITE(TRANSPORT_LOG_DEBUG, _TRANSPORT_LOG_TAG, __VA_ARGS__)
-#define TRANSPORT_LOGD_AUX(log, ...) \
- TRANSPORT_LOG_WRITE_AUX(log, TRANSPORT_LOG_DEBUG, _TRANSPORT_LOG_TAG, \
- __VA_ARGS__)
-#define TRANSPORT_LOGD_MEM(d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM(TRANSPORT_LOG_DEBUG, _TRANSPORT_LOG_TAG, d, d_sz, \
- __VA_ARGS__)
-#define TRANSPORT_LOGD_MEM_AUX(log, d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM_AUX(log, TRANSPORT_LOG_DEBUG, _TRANSPORT_LOG_TAG, d, \
- d_sz, __VA_ARGS__)
-#else
-#define TRANSPORT_LOGD(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGD_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGD_MEM(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGD_MEM_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
-#if TRANSPORT_LOG_ENABLED_INFO
-#define TRANSPORT_LOGI(...) \
- TRANSPORT_LOG_WRITE(TRANSPORT_LOG_INFO, _TRANSPORT_LOG_TAG, __VA_ARGS__)
-#define TRANSPORT_LOGI_AUX(log, ...) \
- TRANSPORT_LOG_WRITE_AUX(log, TRANSPORT_LOG_INFO, _TRANSPORT_LOG_TAG, \
- __VA_ARGS__)
-#define TRANSPORT_LOGI_MEM(d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM(TRANSPORT_LOG_INFO, _TRANSPORT_LOG_TAG, d, d_sz, \
- __VA_ARGS__)
-#define TRANSPORT_LOGI_MEM_AUX(log, d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM_AUX(log, TRANSPORT_LOG_INFO, _TRANSPORT_LOG_TAG, d, \
- d_sz, __VA_ARGS__)
-#else
-#define TRANSPORT_LOGI(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGI_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGI_MEM(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGI_MEM_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
-#if TRANSPORT_LOG_ENABLED_WARN
-#define TRANSPORT_LOGW(...) \
- TRANSPORT_LOG_WRITE(TRANSPORT_LOG_WARN, _TRANSPORT_LOG_TAG, __VA_ARGS__)
-#define TRANSPORT_LOGW_AUX(log, ...) \
- TRANSPORT_LOG_WRITE_AUX(log, TRANSPORT_LOG_WARN, _TRANSPORT_LOG_TAG, \
- __VA_ARGS__)
-#define TRANSPORT_LOGW_MEM(d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM(TRANSPORT_LOG_WARN, _TRANSPORT_LOG_TAG, d, d_sz, \
- __VA_ARGS__)
-#define TRANSPORT_LOGW_MEM_AUX(log, d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM_AUX(log, TRANSPORT_LOG_WARN, _TRANSPORT_LOG_TAG, d, \
- d_sz, __VA_ARGS__)
-#else
-#define TRANSPORT_LOGW(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGW_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGW_MEM(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGW_MEM_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
-#if TRANSPORT_LOG_ENABLED_ERROR
-#define TRANSPORT_LOGE(...) \
- TRANSPORT_LOG_WRITE(TRANSPORT_LOG_ERROR, _TRANSPORT_LOG_TAG, __VA_ARGS__)
-#define TRANSPORT_LOGE_AUX(log, ...) \
- TRANSPORT_LOG_WRITE_AUX(log, TRANSPORT_LOG_ERROR, _TRANSPORT_LOG_TAG, \
- __VA_ARGS__)
-#define TRANSPORT_LOGE_MEM(d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM(TRANSPORT_LOG_ERROR, _TRANSPORT_LOG_TAG, d, d_sz, \
- __VA_ARGS__)
-#define TRANSPORT_LOGE_MEM_AUX(log, d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM_AUX(log, TRANSPORT_LOG_ERROR, _TRANSPORT_LOG_TAG, d, \
- d_sz, __VA_ARGS__)
-#else
-#define TRANSPORT_LOGE(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGE_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGE_MEM(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGE_MEM_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
-#if TRANSPORT_LOG_ENABLED_FATAL
-#define TRANSPORT_LOGF(...) \
- TRANSPORT_LOG_WRITE(TRANSPORT_LOG_FATAL, _TRANSPORT_LOG_TAG, __VA_ARGS__)
-#define TRANSPORT_LOGF_AUX(log, ...) \
- TRANSPORT_LOG_WRITE_AUX(log, TRANSPORT_LOG_FATAL, _TRANSPORT_LOG_TAG, \
- __VA_ARGS__)
-#define TRANSPORT_LOGF_MEM(d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM(TRANSPORT_LOG_FATAL, _TRANSPORT_LOG_TAG, d, d_sz, \
- __VA_ARGS__)
-#define TRANSPORT_LOGF_MEM_AUX(log, d, d_sz, ...) \
- TRANSPORT_LOG_WRITE_MEM_AUX(log, TRANSPORT_LOG_FATAL, _TRANSPORT_LOG_TAG, d, \
- d_sz, __VA_ARGS__)
-#else
-#define TRANSPORT_LOGF(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGF_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGF_MEM(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#define TRANSPORT_LOGF_MEM_AUX(...) _TRANSPORT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
-#define TRANSPORT_LOGV_STR(s) TRANSPORT_LOGV("%s", (s))
-#define TRANSPORT_LOGD_STR(s) TRANSPORT_LOGD("%s", (s))
-#define TRANSPORT_LOGI_STR(s) TRANSPORT_LOGI("%s", (s))
-#define TRANSPORT_LOGW_STR(s) TRANSPORT_LOGW("%s", (s))
-#define TRANSPORT_LOGE_STR(s) TRANSPORT_LOGE("%s", (s))
-#define TRANSPORT_LOGF_STR(s) TRANSPORT_LOGF("%s", (s))
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Output to standard error stream. Library uses it by default, though in few
- * cases it could be necessary to specify it explicitly. For example, when
- * transport_log library is compiled with TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT,
- * application must define and initialize global output variable:
- *
- * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {TRANSPORT_LOG_OUT_STDERR};
- *
- * Another example is when using custom output, stderr could be used as a
- * fallback when custom output facility failed to initialize:
- *
- * transport_log_set_output_v(TRANSPORT_LOG_OUT_STDERR);
- */
-enum { TRANSPORT_LOG_OUT_STDERR_MASK = TRANSPORT_LOG_PUT_STD };
-void transport_log_out_stderr_callback(const transport_log_message *const msg,
- void *arg);
-#define TRANSPORT_LOG_OUT_STDERR \
- TRANSPORT_LOG_OUT_STDERR_MASK, 0, transport_log_out_stderr_callback
-
-/* Predefined spec for stderr. Uses global format options
- * (TRANSPORT_LOG_GLOBAL_FORMAT) and TRANSPORT_LOG_OUT_STDERR. Could be used to
- * force output to stderr for a particular message. Example:
- *
- * f = fopen("foo.log", "w");
- * if (!f)
- * TRANSPORT_LOGE_AUX(TRANSPORT_LOG_STDERR, "Failed to open log file");
- */
-#define TRANSPORT_LOG_STDERR (&_transport_log_stderr_spec)
+} // namespace utils
-#ifdef __cplusplus
-}
-#endif \ No newline at end of file
+#define TRANSPORT_LOG_INFO ::utils::LogInfo::getInstance().getStream()
+#define TRANSPORT_LOG_WARNING ::utils::LogWarning::getInstance().getStream()
+#define TRANSPORT_LOG_ERROR ::utils::LogError::getInstance().getStream()
+#define TRANSPORT_LOG_FATAL ::utils::LogFatal::getInstance().getStream()
diff --git a/libtransport/includes/hicn/transport/utils/membuf.h b/libtransport/includes/hicn/transport/utils/membuf.h
index 0db87e9dd..6f92c2208 100644
--- a/libtransport/includes/hicn/transport/utils/membuf.h
+++ b/libtransport/includes/hicn/transport/utils/membuf.h
@@ -719,8 +719,8 @@ class MemBuf {
/**
* Override operator == and !=
*/
- bool operator ==(const MemBuf &other);
- bool operator !=(const MemBuf &other);
+ bool operator==(const MemBuf& other);
+ bool operator!=(const MemBuf& other);
// /**
// * Iteration support: a chain of MemBufs may be iterated through using
diff --git a/libtransport/includes/hicn/transport/utils/move_wrapper.h b/libtransport/includes/hicn/transport/utils/move_wrapper.h
index 3aba345d6..5dc3b461d 100644
--- a/libtransport/includes/hicn/transport/utils/move_wrapper.h
+++ b/libtransport/includes/hicn/transport/utils/move_wrapper.h
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Copyright 2017 Facebook, Inc.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/libtransport/includes/hicn/transport/utils/object_pool.h b/libtransport/includes/hicn/transport/utils/object_pool.h
index a5e8b2eef..d9b28e663 100644
--- a/libtransport/includes/hicn/transport/utils/object_pool.h
+++ b/libtransport/includes/hicn/transport/utils/object_pool.h
@@ -15,9 +15,7 @@
#pragma once
-// TODO
#include <hicn/transport/utils/branch_prediction.h>
-#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/spinlock.h>
#include <deque>
@@ -34,7 +32,6 @@ class ObjectPool {
void operator()(T *t) {
if (pool_) {
- TRANSPORT_LOGV("Back in pool");
pool_->add(t);
} else {
delete t;
diff --git a/libtransport/includes/hicn/transport/utils/singleton.h b/libtransport/includes/hicn/transport/utils/singleton.h
index 7fd8b912f..4b7b19c0a 100644
--- a/libtransport/includes/hicn/transport/utils/singleton.h
+++ b/libtransport/includes/hicn/transport/utils/singleton.h
@@ -20,7 +20,7 @@
namespace utils {
template <typename T>
-class Singleton {
+class Singleton : NonCopyable {
public:
static T& getInstance() {
static T instance;
@@ -30,10 +30,6 @@ class Singleton {
protected:
Singleton() {}
~Singleton() {}
-
- public:
- Singleton(Singleton const&) = delete;
- Singleton& operator=(Singleton const&) = delete;
};
} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/CMakeLists.txt b/libtransport/src/CMakeLists.txt
index 079427fea..5e0cd38e7 100644
--- a/libtransport/src/CMakeLists.txt
+++ b/libtransport/src/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
include(GNUInstallDirs)
set(ASIO_STANDALONE 1)
@@ -31,17 +29,16 @@ configure_file("config.h.in" "hicn/transport/config.h" @ONLY)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/hicn/transport/config.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hicn/transport
- COMPONENT lib${LIBTRANSPORT}-dev
+ COMPONENT ${LIBTRANSPORT_COMPONENT}-dev
)
install(
FILES "transport.config"
DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
- COMPONENT lib${LIBTRANSPORT}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
)
list(APPEND COMPILER_DEFINITIONS
- "-DTRANSPORT_LOG_DEF_LEVEL=TRANSPORT_LOG_${TRANSPORT_LOG_LEVEL}"
"-DASIO_STANDALONE"
)
@@ -67,42 +64,32 @@ endif ()
if (${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -isystem -lm")
- add_subdirectory(io_modules)
endif()
-if (DISABLE_SHARED_LIBRARIES)
- build_library(${LIBTRANSPORT}
- STATIC
- SOURCES ${SOURCE_FILES} ${HEADER_FILES}
- INSTALL_HEADERS ${LIBHICNTRANSPORT_TO_INSTALL_HEADER_FILES}
- LINK_LIBRARIES ${LIBRARIES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT lib${LIBTRANSPORT}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- HEADER_ROOT_DIR hicn/transport
- DEFINITIONS ${COMPILER_DEFINITIONS}
- VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
- )
-else ()
- build_library(${LIBTRANSPORT}
- STATIC SHARED
- SOURCES ${SOURCE_FILES} ${HEADER_FILES}
- INSTALL_HEADERS ${LIBHICNTRANSPORT_TO_INSTALL_HEADER_FILES}
- LINK_LIBRARIES ${LIBRARIES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT lib${LIBTRANSPORT}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- HEADER_ROOT_DIR hicn/transport
- DEFINITIONS ${COMPILER_DEFINITIONS}
- VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
- )
-endif ()
+set (BUILD_TYPES "STATIC")
-# io modules
-if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Android")
- add_subdirectory(io_modules)
+if (NOT DISABLE_SHARED_LIBRARIES)
+ list(APPEND BUILD_TYPES
+ "SHARED"
+ )
endif()
+add_subdirectory(io_modules)
+
+build_library(${LIBTRANSPORT}
+ ${BUILD_TYPES}
+ SOURCES ${SOURCE_FILES} ${HEADER_FILES}
+ INSTALL_HEADERS ${LIBHICNTRANSPORT_TO_INSTALL_HEADER_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ OBJECT_LIBRARIES ${THIRD_PARTY_OBJECT_LIBRARIES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ HEADER_ROOT_DIR hicn/transport
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
+)
+
if (${BUILD_TESTS})
add_subdirectory(test)
endif()
diff --git a/libtransport/src/auth/CMakeLists.txt b/libtransport/src/auth/CMakeLists.txt
index 0e7b5832b..699bc1050 100644
--- a/libtransport/src/auth/CMakeLists.txt
+++ b/libtransport/src/auth/CMakeLists.txt
@@ -11,12 +11,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/signer.cc
${CMAKE_CURRENT_SOURCE_DIR}/verifier.cc
${CMAKE_CURRENT_SOURCE_DIR}/identity.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.cc
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/auth/crypto_hash.cc b/libtransport/src/auth/crypto_hash.cc
new file mode 100644
index 000000000..b4b0a8b81
--- /dev/null
+++ b/libtransport/src/auth/crypto_hash.cc
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/auth/crypto_hash.h>
+
+using namespace std;
+
+namespace transport {
+namespace auth {
+
+CryptoHash::CryptoHash() : CryptoHash(CryptoHashType::UNKNOWN) {}
+
+CryptoHash::CryptoHash(const CryptoHash &other)
+ : digest_type_(other.digest_type_),
+ digest_(other.digest_),
+ digest_size_(other.digest_size_) {}
+
+CryptoHash::CryptoHash(CryptoHash &&other)
+ : digest_type_(move(other.digest_type_)),
+ digest_(other.digest_),
+ digest_size_(other.digest_size_) {
+ other.reset();
+}
+
+CryptoHash::CryptoHash(CryptoHashType hash_type) { setType(hash_type); }
+
+CryptoHash::CryptoHash(const uint8_t *hash, size_t size,
+ CryptoHashType hash_type)
+ : digest_type_(hash_type), digest_size_(size) {
+ digest_.resize(size);
+ memcpy(digest_.data(), hash, size);
+}
+
+CryptoHash::CryptoHash(const vector<uint8_t> &hash, CryptoHashType hash_type)
+ : CryptoHash(hash.data(), hash.size(), hash_type) {}
+
+CryptoHash &CryptoHash::operator=(const CryptoHash &other) {
+ digest_type_ = other.digest_type_;
+ digest_ = other.digest_;
+ digest_size_ = other.digest_size_;
+ return *this;
+}
+
+bool CryptoHash::operator==(const CryptoHash &other) const {
+ return (digest_type_ == other.digest_type_ && digest_ == other.digest_);
+}
+
+void CryptoHash::computeDigest(const uint8_t *buffer, size_t len) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(digest_type_);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ EVP_Digest(buffer, len, digest_.data(), (unsigned int *)&digest_size_,
+ (*hash_evp)(), nullptr);
+}
+
+void CryptoHash::computeDigest(const vector<uint8_t> &buffer) {
+ computeDigest(buffer.data(), buffer.size());
+}
+
+void CryptoHash::computeDigest(const utils::MemBuf *buffer) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(digest_type_);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ EVP_MD_CTX *mcdtx = EVP_MD_CTX_new();
+ const utils::MemBuf *p = buffer;
+
+ if (EVP_DigestInit_ex(mcdtx, (*hash_evp)(), nullptr) == 0) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestUpdate(mcdtx, p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
+
+ p = p->next();
+ } while (p != buffer);
+
+ if (EVP_DigestFinal_ex(mcdtx, digest_.data(),
+ (unsigned int *)&digest_size_) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
+
+ EVP_MD_CTX_free(mcdtx);
+}
+
+vector<uint8_t> CryptoHash::getDigest() const { return digest_; }
+
+string CryptoHash::getStringDigest() const {
+ stringstream string_digest;
+
+ string_digest << hex << setfill('0');
+
+ for (auto byte : digest_) {
+ string_digest << hex << setw(2) << static_cast<int>(byte);
+ }
+
+ return string_digest.str();
+}
+
+CryptoHashType CryptoHash::getType() const { return digest_type_; }
+
+size_t CryptoHash::getSize() const { return digest_size_; }
+
+void CryptoHash::setType(CryptoHashType hash_type) {
+ reset();
+ digest_type_ = hash_type;
+ digest_size_ = CryptoHash::getSize(hash_type);
+ digest_.resize(digest_size_);
+}
+
+void CryptoHash::display() {
+ switch (digest_type_) {
+ case CryptoHashType::SHA256:
+ cout << "SHA256";
+ break;
+ case CryptoHashType::SHA512:
+ cout << "SHA512";
+ break;
+ case CryptoHashType::BLAKE2S256:
+ cout << "BLAKE2s256";
+ break;
+ case CryptoHashType::BLAKE2B512:
+ cout << "BLAKE2b512";
+ break;
+ default:
+ cout << "UNKNOWN";
+ break;
+ }
+
+ cout << ": " << getStringDigest() << endl;
+}
+
+void CryptoHash::reset() {
+ digest_type_ = CryptoHashType::UNKNOWN;
+ digest_.clear();
+ digest_size_ = 0;
+}
+
+CryptoHashEVP CryptoHash::getEVP(CryptoHashType hash_type) {
+ switch (hash_type) {
+ case CryptoHashType::SHA256:
+ return &EVP_sha256;
+ break;
+ case CryptoHashType::SHA512:
+ return &EVP_sha512;
+ break;
+ case CryptoHashType::BLAKE2S256:
+ return &EVP_blake2s256;
+ break;
+ case CryptoHashType::BLAKE2B512:
+ return &EVP_blake2b512;
+ break;
+ default:
+ return nullptr;
+ break;
+ }
+}
+
+size_t CryptoHash::getSize(CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ return 0;
+ }
+
+ return EVP_MD_size((*hash_evp)());
+}
+
+bool CryptoHash::compareDigest(const uint8_t *digest1, const uint8_t *digest2,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ return false;
+ }
+
+ return !static_cast<bool>(
+ memcmp(digest1, digest2, CryptoHash::getSize(hash_type)));
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/auth/crypto_suite.cc b/libtransport/src/auth/crypto_suite.cc
new file mode 100644
index 000000000..7e898ef09
--- /dev/null
+++ b/libtransport/src/auth/crypto_suite.cc
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/auth/crypto_suite.h>
+
+namespace transport {
+namespace auth {
+
+CryptoSuite getSuite(int nid) {
+ switch (nid) {
+ case NID_ecdsa_with_SHA256:
+ return CryptoSuite::ECDSA_SHA256;
+ break;
+ case NID_ecdsa_with_SHA512:
+ return CryptoSuite::ECDSA_SHA512;
+ break;
+ case NID_sha256WithRSAEncryption:
+ return CryptoSuite::RSA_SHA256;
+ break;
+ case NID_sha512WithRSAEncryption:
+ return CryptoSuite::RSA_SHA512;
+ break;
+ case NID_hmacWithSHA256:
+ return CryptoSuite::HMAC_SHA256;
+ break;
+ case NID_hmacWithSHA512:
+ return CryptoSuite::HMAC_SHA512;
+ break;
+ case NID_dsa_with_SHA256:
+ return CryptoSuite::DSA_SHA256;
+ break;
+ case NID_dsa_with_SHA512:
+ return CryptoSuite::DSA_SHA512;
+ break;
+ default:
+ return CryptoSuite::UNKNOWN;
+ break;
+ }
+}
+
+CryptoHashType getHashType(CryptoSuite suite) {
+ switch (suite) {
+ case CryptoSuite::ECDSA_BLAKE2B512:
+ case CryptoSuite::RSA_BLAKE2B512:
+ case CryptoSuite::HMAC_BLAKE2B512:
+ case CryptoSuite::DSA_BLAKE2B512:
+ return CryptoHashType::BLAKE2B512;
+ case CryptoSuite::ECDSA_BLAKE2S256:
+ case CryptoSuite::RSA_BLAKE2S256:
+ case CryptoSuite::HMAC_BLAKE2S256:
+ case CryptoSuite::DSA_BLAKE2S256:
+ return CryptoHashType::BLAKE2S256;
+ case CryptoSuite::ECDSA_SHA256:
+ case CryptoSuite::RSA_SHA256:
+ case CryptoSuite::HMAC_SHA256:
+ case CryptoSuite::DSA_SHA256:
+ return CryptoHashType::SHA256;
+ case CryptoSuite::ECDSA_SHA512:
+ case CryptoSuite::RSA_SHA512:
+ case CryptoSuite::HMAC_SHA512:
+ case CryptoSuite::DSA_SHA512:
+ return CryptoHashType::SHA512;
+ default:
+ return CryptoHashType::UNKNOWN;
+ }
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/auth/identity.cc b/libtransport/src/auth/identity.cc
index bd787b9b6..f56532033 100644
--- a/libtransport/src/auth/identity.cc
+++ b/libtransport/src/auth/identity.cc
@@ -17,90 +17,262 @@
using namespace std;
+// function needed to create the a certificate
+static bool _addRandomSerial(X509 *cert) {
+ unsigned long serial = 0;
+ unsigned char serial_bytes[sizeof(serial)];
+
+ // Construct random positive serial number.
+ RAND_bytes(serial_bytes, sizeof(serial_bytes));
+ serial_bytes[0] &= 0x7F;
+ serial = 0;
+ for (size_t i = 0; i < sizeof(serial_bytes); i++) {
+ serial = (256 * serial) + serial_bytes[i];
+ }
+ ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
+ return true;
+}
+
+static bool _addValidityPeriod(X509 *cert, size_t validityDays) {
+ // Set the validity from now for the specified number of days.
+ X509_gmtime_adj(X509_get_notBefore(cert), (long)0);
+ X509_gmtime_adj(X509_get_notAfter(cert), (long)(60 * 60 * 24 * validityDays));
+ return true;
+}
+
+static bool _addSubjectName(X509 *cert, const char *subjectname) {
+ // Set up the simple subject name and issuer name for the certificate.
+ X509_NAME *name = X509_get_subject_name(cert);
+
+ if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
+ (unsigned char *)subjectname, -1, -1, 0)) {
+ if (X509_set_issuer_name(cert, name)) {
+ return true;
+ }
+ }
+ return false;
+}
+static bool _addCertificateExtensionWithContext(X509 *cert, int nid,
+ const char *value) {
+ X509_EXTENSION *extension;
+ X509V3_CTX context;
+
+ X509V3_set_ctx_nodb(&context);
+ X509V3_set_ctx(&context, cert, cert, NULL, NULL, 0);
+ extension = X509V3_EXT_conf_nid(NULL, &context, nid, value);
+ if (extension == NULL) {
+ return false;
+ }
+ X509_add_ext(cert, extension, -1);
+ X509_EXTENSION_free(extension);
+ return true;
+}
+static bool _addCertificateExtension(X509 *cert, int nid, const char *value) {
+ X509_EXTENSION *extension = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
+ if (extension == NULL) {
+ return false;
+ }
+ X509_add_ext(cert, extension, -1);
+ X509_EXTENSION_free(extension);
+ return true;
+}
+
+static bool _addExtensions(X509 *cert) {
+ // Add the necessary extensions.
+ if (_addCertificateExtension(cert, NID_basic_constraints,
+ "critical,CA:FALSE") == true) {
+ if (_addCertificateExtension(
+ cert, NID_key_usage,
+ "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,"
+ "keyAgreement") == true) {
+ if (_addCertificateExtension(cert, NID_ext_key_usage, "clientAuth") ==
+ true) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+static bool _addKeyIdentifier(X509 *cert) {
+ unsigned char spkid[SHA256_DIGEST_LENGTH];
+ char spkid_hex[1 + 2 * SHA256_DIGEST_LENGTH];
+ if (ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(),
+ X509_get_X509_PUBKEY(cert), spkid, NULL)) {
+ for (int i = 0; i < 32; i++) {
+ snprintf(&spkid_hex[2 * i], 3, "%02X", (unsigned)spkid[i]);
+ }
+ if (_addCertificateExtension(cert, NID_subject_key_identifier, spkid_hex) ==
+ true) {
+ if (_addCertificateExtensionWithContext(
+ cert, NID_authority_key_identifier, "keyid:always") == true) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
namespace transport {
namespace auth {
Identity::Identity(const string &keystore_path, const string &keystore_pwd,
CryptoSuite suite, unsigned int signature_len,
unsigned int validity_days, const string &subject_name)
- : identity_(nullptr), signer_(nullptr) {
- parcSecurity_Init();
-
- bool success = parcPkcs12KeyStore_CreateFile(
- keystore_path.c_str(), keystore_pwd.c_str(), subject_name.c_str(),
- parcCryptoSuite_GetSigningAlgorithm(static_cast<PARCCryptoSuite>(suite)),
- signature_len, validity_days);
+ : cert_(X509_new(), ::X509_free) {
+ // create the file and complete it.
+ // first we create the certificate
- parcAssertTrue(
- success,
- "parcPkcs12KeyStore_CreateFile('%s', '%s', '%s', %d, %d, %d) failed.",
- keystore_path.c_str(), keystore_pwd.c_str(), subject_name.c_str(),
- static_cast<int>(suite), static_cast<int>(signature_len), validity_days);
+ // to create the cert we will need a private key
- PARCIdentityFile *identity_file =
- parcIdentityFile_Create(keystore_path.c_str(), keystore_pwd.c_str());
+ std::shared_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), EVP_PKEY_free);
- identity_ =
- parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
+ if (suite == CryptoSuite::RSA_SHA512 || suite == CryptoSuite::RSA_SHA256) {
+ RSA *rsa = RSA_new();
+ BIGNUM *pub_exp;
- PARCSigner *signer = parcIdentity_CreateSigner(
- identity_,
- parcCryptoSuite_GetCryptoHash(static_cast<PARCCryptoSuite>(suite)));
+ pub_exp = BN_new();
- signer_ = make_shared<AsymmetricSigner>(signer);
-
- parcSigner_Release(&signer);
- parcIdentityFile_Release(&identity_file);
+ BN_set_word(pub_exp, RSA_F4);
+ if (1 != RSA_generate_key_ex(rsa, signature_len, pub_exp, NULL))
+ throw errors::RuntimeException("can't generate the key");
+ if (1 != EVP_PKEY_set1_RSA(privateKey.get(), rsa))
+ throw errors::RuntimeException("can't generate the key");
+ } else if (suite == CryptoSuite::ECDSA_SHA256) {
+ int curve_params;
+ switch (signature_len) {
+ case 160u:
+ curve_params = NID_secp160k1;
+ break;
+ case 192u:
+ curve_params = NID_secp192k1;
+ break;
+ case 224u:
+ curve_params = NID_secp224k1;
+ break;
+ case 256u:
+ curve_params = NID_secp256k1;
+ break;
+ default:
+ curve_params = -1;
+ break;
+ }
+ if (curve_params == -1)
+ throw errors::RuntimeException("can't generate the key");
+ EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve_params);
+ if (ec_key == NULL)
+ throw errors::RuntimeException("can't create ecdsa key from curve");
+ EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_generate_key(ec_key) == 0)
+ throw errors::RuntimeException("can't generate the ecdsa key");
+ if (EVP_PKEY_set1_EC_KEY(privateKey.get(), ec_key) == 0)
+ throw errors::RuntimeException("can't generate the ecdsa key");
+ } else if (suite == CryptoSuite::DSA_SHA256) {
+ DSA *dsa = DSA_new();
+ unsigned char buffer[32];
+ if (RAND_bytes(buffer, sizeof(buffer)) != 1) {
+ throw errors::RuntimeException("can't generate the key");
+ }
+ if (DSA_generate_parameters_ex(dsa, signature_len, buffer, sizeof(buffer),
+ NULL, NULL, NULL) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (DSA_generate_key(dsa) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ if (EVP_PKEY_set1_DSA(privateKey.get(), dsa) != 1)
+ throw errors::RuntimeException("can't generate the key");
+ }
+ bool success = true;
+ success = success && (X509_set_version(cert_.get(), 2) == 1); // 2 => X509v3
+ success = success && _addRandomSerial(cert_.get());
+ success = success && _addValidityPeriod(cert_.get(), validity_days);
+ success = success && (X509_set_pubkey(cert_.get(), privateKey.get()) == 1);
+ success = success && _addSubjectName(cert_.get(), subject_name.c_str());
+ success = success && _addExtensions(cert_.get());
+ success =
+ success && (X509_sign(cert_.get(), privateKey.get(), EVP_sha256()) != 0);
+ success = success && _addKeyIdentifier(cert_.get());
+ if (!success) {
+ throw errors::RuntimeException("error while creating the certificate");
+ }
+ // the certificate is created. We create the pkcs12 object to write the p12
+ // file
+ PKCS12 *p12 = PKCS12_create(
+ keystore_pwd.c_str(), "ccnxuser", privateKey.get(), cert_.get(), NULL, 0,
+ 0, 0 /*default iter*/, PKCS12_DEFAULT_ITER /*mac_iter*/, 0);
+ filename_ = keystore_path;
+ int fp = open(filename_.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0600);
+ if (fp == -1) throw errors::RuntimeException("impossible to create the file");
+ FILE *fp_f = fdopen(fp, "wb");
+ if (fp_f == NULL)
+ throw errors::RuntimeException("impossible to create the file");
+ i2d_PKCS12_fp(fp_f, p12);
+ fclose(fp_f);
+ close(fp);
+ std::shared_ptr<EVP_PKEY> publickey(X509_get_pubkey(cert_.get()),
+ EVP_PKEY_free);
+ signer_ = std::shared_ptr<AsymmetricSigner>(
+ new AsymmetricSigner(suite, privateKey, publickey));
+ signer_->signature_len_ = signature_len;
}
Identity::Identity(string &keystore_path, string &keystore_pwd,
CryptoHashType hash_type)
- : identity_(nullptr), signer_(nullptr) {
- parcSecurity_Init();
-
- PARCIdentityFile *identity_file =
- parcIdentityFile_Create(keystore_path.c_str(), keystore_pwd.c_str());
-
- identity_ =
- parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
-
- PARCSigner *signer = parcIdentity_CreateSigner(
- identity_, static_cast<PARCCryptoHashType>(hash_type));
-
- signer_ = make_shared<AsymmetricSigner>(signer);
-
- parcSigner_Release(&signer);
- parcIdentityFile_Release(&identity_file);
+ : cert_(X509_new(), ::X509_free) {
+ filename_ = keystore_path;
+ pwd_ = keystore_path;
+ // get the key and certificate by first opening the keystore file
+ FILE *p12file = fopen(keystore_path.c_str(), "r");
+ if (p12file == NULL)
+ throw errors::RuntimeException("impossible open keystore");
+ PKCS12 *p12 = d2i_PKCS12_fp(p12file, NULL);
+ EVP_PKEY *privatekey;
+ EVP_PKEY *publickey;
+ X509 *cert = cert_.get();
+ // now we parse the file to get the first key and certificate
+ if (1 != PKCS12_parse(p12, keystore_pwd.c_str(), &privatekey, &cert, NULL))
+ throw errors::RuntimeException("impossible to get the private key");
+ publickey = X509_get_pubkey(cert);
+ // to have the cryptosuite we use the nid number that is used to identify the
+ // suite.
+ CryptoSuite suite = getSuite(X509_get_signature_nid(cert));
+ signer_ = std::shared_ptr<AsymmetricSigner>(new AsymmetricSigner(
+ suite, std::shared_ptr<EVP_PKEY>(privatekey, EVP_PKEY_free),
+ std::shared_ptr<EVP_PKEY>(publickey, EVP_PKEY_free)));
+ PKCS12_free(p12);
}
-Identity::Identity(const Identity &other)
- : identity_(nullptr), signer_(other.signer_) {
- parcSecurity_Init();
- identity_ = parcIdentity_Acquire(other.identity_);
+Identity::Identity(const Identity &other) {
+ pwd_ = other.pwd_;
+ filename_ = other.filename_;
+ signer_ = other.signer_;
+ cert_ = other.cert_;
}
-Identity::Identity(Identity &&other)
- : identity_(nullptr), signer_(move(other.signer_)) {
- parcSecurity_Init();
- identity_ = parcIdentity_Acquire(other.identity_);
- parcIdentity_Release(&other.identity_);
+Identity::Identity(Identity &&other) {
+ signer_ = std::move(other.signer_);
+ other.signer_.reset();
+ cert_ = std::move(other.cert_);
+ other.cert_.reset();
+ pwd_ = other.pwd_;
+ other.pwd_ = "";
+ filename_ = other.filename_;
+ other.filename_ = "";
+ signer_ = other.signer_;
+ other.signer_ = nullptr;
}
-Identity::~Identity() {
- if (identity_) parcIdentity_Release(&identity_);
- parcSecurity_Fini();
-}
+Identity::~Identity() {}
shared_ptr<AsymmetricSigner> Identity::getSigner() const { return signer_; }
-string Identity::getFilename() const {
- return string(parcIdentity_GetFileName(identity_));
-}
+string Identity::getFilename() const { return filename_; }
-string Identity::getPassword() const {
- return string(parcIdentity_GetPassWord(identity_));
+std::shared_ptr<X509> Identity::getCertificate() const { return cert_; }
+std::shared_ptr<EVP_PKEY> Identity::getPrivateKey() const {
+ return signer_->key_;
}
+string Identity::getPassword() const { return pwd_; }
+
Identity Identity::generateIdentity(const string &subject_name) {
string keystore_name = "keystore";
string keystore_password = "password";
diff --git a/libtransport/src/auth/signer.cc b/libtransport/src/auth/signer.cc
index 99c3d099d..884e850ca 100644
--- a/libtransport/src/auth/signer.cc
+++ b/libtransport/src/auth/signer.cc
@@ -15,193 +15,214 @@
#include <hicn/transport/auth/signer.h>
-extern "C" {
-#ifndef _WIN32
-TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
-#endif
-#include <hicn/hicn.h>
-}
-
-#include <chrono>
-
-#define ALLOW_UNALIGNED_READS 1
-
using namespace std;
namespace transport {
namespace auth {
-Signer::Signer() : signer_(nullptr), key_id_(nullptr) { parcSecurity_Init(); }
+// ---------------------------------------------------------
+// Base Signer
+// ---------------------------------------------------------
+Signer::Signer()
+ : suite_(CryptoSuite::UNKNOWN), signature_len_(0), key_(nullptr) {}
-Signer::Signer(PARCSigner *signer) : Signer() { setSigner(signer); }
-
-Signer::~Signer() {
- if (signer_) parcSigner_Release(&signer_);
- if (key_id_) parcKeyId_Release(&key_id_);
- parcSecurity_Fini();
-}
+Signer::~Signer() {}
void Signer::signPacket(PacketPtr packet) {
- parcAssertNotNull(signer_, "Expected non-null signer");
-
- const utils::MemBuf &header_chain = *packet;
+ assert(key_ != nullptr);
core::Packet::Format format = packet->getFormat();
- auto suite = getCryptoSuite();
- size_t signature_len = getSignatureSize();
if (!packet->authenticationHeader()) {
throw errors::MalformedAHPacketException();
}
- packet->setSignatureSize(signature_len);
+ // Set signature size
+ size_t signature_field_len = getSignatureFieldSize();
+ packet->setSignatureSize(signature_field_len);
+ packet->setSignatureSizeGap(0u);
// Copy IP+TCP / ICMP header before zeroing them
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
- packet->resetForHash();
- // Fill in the HICN_AH header
+ // Fill in the hICN AH header
auto now = chrono::duration_cast<chrono::milliseconds>(
chrono::system_clock::now().time_since_epoch())
.count();
packet->setSignatureTimestamp(now);
- packet->setValidationAlgorithm(suite);
+ packet->setValidationAlgorithm(suite_);
- // Set the key ID
- KeyId key_id;
- key_id.first = static_cast<uint8_t *>(
- parcBuffer_Overlay((PARCBuffer *)parcKeyId_GetKeyId(key_id_), 0));
- packet->setKeyId(key_id);
+ // Set key ID
+ vector<uint8_t> key_id = key_id_.getDigest();
+ packet->setKeyId({key_id.data(), key_id.size()});
- // Calculate hash
- CryptoHasher hasher(parcSigner_GetCryptoHasher(signer_));
- const utils::MemBuf *current = &header_chain;
+ // Reset fields to compute the packet hash
+ packet->resetForHash();
- hasher.init();
+ // Compute the signature and put it in the packet
+ signBuffer(packet);
+ hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
- do {
- hasher.updateBytes(current->data(), current->length());
- current = current->next();
- } while (current != &header_chain);
+ // Set the gap between the signature field size and the signature real size.
+ packet->setSignatureSizeGap(signature_field_len - signature_len_);
+ memcpy(packet->getSignature(), signature_.data(), signature_len_);
+}
- CryptoHash hash = hasher.finalize();
+void Signer::signBuffer(const std::vector<uint8_t> &buffer) {
+ assert(key_ != nullptr);
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
- // Compute signature
- PARCSignature *signature = parcSigner_SignDigestNoAlloc(
- signer_, hash.hash_, packet->getSignature(), (uint32_t)signature_len);
- PARCBuffer *buffer = parcSignature_GetSignature(signature);
- size_t bytes_len = parcBuffer_Remaining(buffer);
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
- if (bytes_len > signature_len) {
- throw errors::MalformedAHPacketException();
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
}
- // Put signature in AH header
- hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
- // Release allocated objects
- parcSignature_Release(&signature);
-}
+ if (EVP_DigestSignUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
-void Signer::setSigner(PARCSigner *signer) {
- parcAssertNotNull(signer, "Expected non-null signer");
+ if (EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len_) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
- if (signer_) parcSigner_Release(&signer_);
- if (key_id_) parcKeyId_Release(&key_id_);
+ signature_.resize(signature_len_);
- signer_ = parcSigner_Acquire(signer);
- key_id_ = parcSigner_CreateKeyId(signer_);
-}
+ if (EVP_DigestSignFinal(mdctx.get(), signature_.data(), &signature_len_) !=
+ 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
-size_t Signer::getSignatureSize() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return parcSigner_GetSignatureSize(signer_);
+ signature_.resize(signature_len_);
}
-CryptoSuite Signer::getCryptoSuite() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return static_cast<CryptoSuite>(parcSigner_GetCryptoSuite(signer_));
-}
+void Signer::signBuffer(const utils::MemBuf *buffer) {
+ assert(key_ != nullptr);
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
-CryptoHashType Signer::getCryptoHashType() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return static_cast<CryptoHashType>(parcSigner_GetCryptoHashType(signer_));
-}
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
-PARCSigner *Signer::getParcSigner() const { return signer_; }
+ const utils::MemBuf *p = buffer;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
-PARCKeyStore *Signer::getParcKeyStore() const {
- parcAssertNotNull(signer_, "Expected non-null signer");
- return parcSigner_GetKeyStore(signer_);
-}
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
+
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestSignUpdate(mdctx.get(), p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
-AsymmetricSigner::AsymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store) {
- parcAssertNotNull(key_store, "Expected non-null key_store");
+ p = p->next();
+ } while (p != buffer);
- auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
+ if (EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len_) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
+
+ signature_.resize(signature_len_);
- switch (suite) {
- case CryptoSuite::DSA_SHA256:
- case CryptoSuite::RSA_SHA256:
- case CryptoSuite::RSA_SHA512:
- case CryptoSuite::ECDSA_256K1:
- break;
- default:
- throw errors::RuntimeException(
- "Invalid crypto suite for asymmetric signer");
+ if (EVP_DigestSignFinal(mdctx.get(), signature_.data(), &signature_len_) !=
+ 1) {
+ throw errors::RuntimeException("Digest computation failed");
}
- setSigner(
- parcSigner_Create(parcPublicKeySigner_Create(key_store, crypto_suite),
- PARCPublicKeySignerAsSigner));
+ signature_.resize(signature_len_);
}
-SymmetricSigner::SymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store) {
- parcAssertNotNull(key_store, "Expected non-null key_store");
+vector<uint8_t> Signer::getSignature() const { return signature_; }
- auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
+size_t Signer::getSignatureSize() const { return signature_len_; }
- switch (suite) {
- case CryptoSuite::HMAC_SHA256:
- case CryptoSuite::HMAC_SHA512:
- break;
- default:
- throw errors::RuntimeException(
- "Invalid crypto suite for symmetric signer");
+size_t Signer::getSignatureFieldSize() const {
+ if (signature_len_ % 4 == 0) {
+ return signature_len_;
}
- setSigner(parcSigner_Create(parcSymmetricKeySigner_Create(
- (PARCSymmetricKeyStore *)key_store,
- parcCryptoSuite_GetCryptoHash(crypto_suite)),
- PARCSymmetricKeySignerAsSigner));
+ return (signature_len_ + 4) - (signature_len_ % 4);
}
-SymmetricSigner::SymmetricSigner(CryptoSuite suite, const string &passphrase) {
- auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
-
- switch (suite) {
- case CryptoSuite::HMAC_SHA256:
- case CryptoSuite::HMAC_SHA512:
- break;
- default:
- throw errors::RuntimeException(
- "Invalid crypto suite for symmetric signer");
- }
+CryptoHashType Signer::getHashType() const {
+ return ::transport::auth::getHashType(suite_);
+}
+
+CryptoSuite Signer::getSuite() const { return suite_; }
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_PutString(composer, passphrase.c_str());
- PARCBuffer *key_buf = parcBufferComposer_ProduceBuffer(composer);
- parcBufferComposer_Release(&composer);
+// ---------------------------------------------------------
+// Void Signer
+// ---------------------------------------------------------
+void VoidSigner::signPacket(PacketPtr packet){};
- PARCSymmetricKeyStore *key_store = parcSymmetricKeyStore_Create(key_buf);
- PARCSymmetricKeySigner *key_signer = parcSymmetricKeySigner_Create(
- key_store, parcCryptoSuite_GetCryptoHash(crypto_suite));
+void VoidSigner::signBuffer(const std::vector<uint8_t> &buffer){};
- setSigner(parcSigner_Create(key_signer, PARCSymmetricKeySignerAsSigner));
+void VoidSigner::signBuffer(const utils::MemBuf *buffer){};
+
+// ---------------------------------------------------------
+// Asymmetric Signer
+// ---------------------------------------------------------
+AsymmetricSigner::AsymmetricSigner(CryptoSuite suite, shared_ptr<EVP_PKEY> key,
+ shared_ptr<EVP_PKEY> pub_key) {
+ suite_ = suite;
+ key_ = key;
+ key_id_ = CryptoHash(getHashType());
+
+ vector<uint8_t> pbk(i2d_PublicKey(pub_key.get(), nullptr));
+ uint8_t *pbk_ptr = pbk.data();
+ int len = i2d_PublicKey(pub_key.get(), &pbk_ptr);
+
+ signature_len_ = EVP_PKEY_size(key.get());
+ signature_.resize(signature_len_);
+ key_id_.computeDigest(pbk_ptr, len);
+}
+
+size_t AsymmetricSigner::getSignatureFieldSize() const {
+ size_t field_size = EVP_PKEY_size(key_.get());
+
+ if (field_size % 4 == 0) {
+ return field_size;
+ }
+
+ return (field_size + 4) - (field_size % 4);
+}
+
+// ---------------------------------------------------------
+// Symmetric Signer
+// ---------------------------------------------------------
+SymmetricSigner::SymmetricSigner(CryptoSuite suite, const string &passphrase) {
+ suite_ = suite;
+ key_ = shared_ptr<EVP_PKEY>(
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, nullptr,
+ (const unsigned char *)passphrase.c_str(),
+ passphrase.size()),
+ EVP_PKEY_free);
+ key_id_ = CryptoHash(getHashType());
+
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(getHashType());
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
- parcSymmetricKeySigner_Release(&key_signer);
- parcSymmetricKeyStore_Release(&key_store);
- parcBuffer_Release(&key_buf);
+ signature_len_ = EVP_MD_size((*hash_evp)());
+ signature_.resize(signature_len_);
+ key_id_.computeDigest((uint8_t *)passphrase.c_str(), passphrase.size());
}
} // namespace auth
diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc
index c6648a763..c9ac1650f 100644
--- a/libtransport/src/auth/verifier.cc
+++ b/libtransport/src/auth/verifier.cc
@@ -16,168 +16,125 @@
#include <hicn/transport/auth/verifier.h>
#include <protocols/errors.h>
-extern "C" {
-#ifndef _WIN32
-TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
-#endif
-#include <hicn/hicn.h>
-}
-
-#include <sys/stat.h>
-
using namespace std;
namespace transport {
namespace auth {
-const std::vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = {
+const vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = {
VerificationPolicy::DROP,
VerificationPolicy::ABORT,
};
+// ---------------------------------------------------------
+// Base Verifier
+// ---------------------------------------------------------
Verifier::Verifier()
- : hasher_(nullptr),
- verifier_(nullptr),
- verification_failed_cb_(interface::VOID_HANDLER),
- failed_policies_(DEFAULT_FAILED_POLICIES) {
- parcSecurity_Init();
- PARCInMemoryVerifier *in_memory_verifier = parcInMemoryVerifier_Create();
- verifier_ =
- parcVerifier_Create(in_memory_verifier, PARCInMemoryVerifierAsVerifier);
- parcInMemoryVerifier_Release(&in_memory_verifier);
-}
+ : verification_failed_cb_(interface::VOID_HANDLER),
+ failed_policies_(DEFAULT_FAILED_POLICIES) {}
-Verifier::~Verifier() {
- if (hasher_) parcCryptoHasher_Release(&hasher_);
- if (verifier_) parcVerifier_Release(&verifier_);
- parcSecurity_Fini();
-}
+Verifier::~Verifier() {}
bool Verifier::verifyPacket(PacketPtr packet) {
- bool valid_packet = false;
core::Packet::Format format = packet->getFormat();
if (!packet->authenticationHeader()) {
throw errors::MalformedAHPacketException();
}
- // Get crypto suite and hash type
- auto suite = static_cast<PARCCryptoSuite>(packet->getValidationAlgorithm());
- PARCCryptoHashType hash_type = parcCryptoSuite_GetCryptoHash(suite);
+ // Get crypto suite, hash type, signature length
+ CryptoSuite suite = packet->getValidationAlgorithm();
+ CryptoHashType hash_type = getHashType(suite);
+ size_t signature_len = packet->getSignatureSizeReal();
// Copy IP+TCP / ICMP header before zeroing them
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
+ packet->setSignatureSizeGap(0u);
- // Fetch packet signature
+ // Retrieve packet signature
uint8_t *packet_signature = packet->getSignature();
- size_t signature_len = Verifier::getSignatureSize(packet);
vector<uint8_t> signature_raw(packet_signature,
packet_signature + signature_len);
- // Create a signature buffer from the raw packet signature
- PARCBuffer *bits =
- parcBuffer_Wrap(signature_raw.data(), signature_len, 0, signature_len);
- parcBuffer_Rewind(bits);
-
- // If the signature algo is ECDSA, the signature might be shorter than the
- // signature field
- PARCSigningAlgorithm algo = parcCryptoSuite_GetSigningAlgorithm(suite);
- if (algo == PARCSigningAlgorithm_ECDSA) {
- while (parcBuffer_HasRemaining(bits) && parcBuffer_GetUint8(bits) == 0)
- ;
- parcBuffer_SetPosition(bits, parcBuffer_Position(bits) - 1);
- }
-
- if (!parcBuffer_HasRemaining(bits)) {
- parcBuffer_Release(&bits);
- return false;
- }
-
- // Create a signature object from the signature buffer
- PARCSignature *signature = parcSignature_Create(
- parcCryptoSuite_GetSigningAlgorithm(suite), hash_type, bits);
-
- // Fetch the key to verify the signature
- KeyId key_buffer = packet->getKeyId();
- PARCBuffer *buffer = parcBuffer_Wrap(key_buffer.first, key_buffer.second, 0,
- key_buffer.second);
- PARCKeyId *key_id = parcKeyId_Create(buffer);
-
// Reset fields that are not used to compute signature
packet->resetForHash();
- // Compute the packet hash
- if (!hasher_)
- setHasher(parcVerifier_GetCryptoHasher(verifier_, key_id, hash_type));
- CryptoHash local_hash = computeHash(packet);
-
- // Compare the packet signature to the locally computed one
- valid_packet = parcVerifier_VerifyDigestSignature(
- verifier_, key_id, local_hash.hash_, suite, signature);
+ // Check signatures
+ bool valid_packet = verifyBuffer(static_cast<utils::MemBuf *>(packet),
+ signature_raw, hash_type);
- // Restore the fields that were reset
+ // Restore header
hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
-
- // Release allocated objects
- parcBuffer_Release(&buffer);
- parcKeyId_Release(&key_id);
- parcSignature_Release(&signature);
- parcBuffer_Release(&bits);
+ packet->setSignatureSizeGap(packet->getSignatureSize() - signature_len);
return valid_packet;
}
-vector<VerificationPolicy> Verifier::verifyPackets(
- const vector<PacketPtr> &packets) {
- vector<VerificationPolicy> policies(packets.size(), VerificationPolicy::DROP);
+Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets) {
+ PolicyMap policies;
+
+ for (const auto &packet : packets) {
+ Suffix suffix = packet->getName().getSuffix();
+ VerificationPolicy policy = VerificationPolicy::ABORT;
- for (unsigned int i = 0; i < packets.size(); ++i) {
- if (verifyPacket(packets[i])) {
- policies[i] = VerificationPolicy::ACCEPT;
+ if (verifyPacket(packet)) {
+ policy = VerificationPolicy::ACCEPT;
}
- callVerificationFailedCallback(packets[i], policies[i]);
+ policies[suffix] = policy;
+ callVerificationFailedCallback(packet, policy);
}
return policies;
}
-vector<VerificationPolicy> Verifier::verifyPackets(
- const vector<PacketPtr> &packets,
- const unordered_map<Suffix, HashEntry> &suffix_map) {
- vector<VerificationPolicy> policies(packets.size(),
- VerificationPolicy::UNKNOWN);
+Verifier::PolicyMap Verifier::verifyHashes(const SuffixMap &packet_map,
+ const SuffixMap &suffix_map) {
+ PolicyMap policies;
- for (unsigned int i = 0; i < packets.size(); ++i) {
- uint32_t suffix = packets[i]->getName().getSuffix();
- auto manifest_hash = suffix_map.find(suffix);
+ for (const auto &packet_hash : packet_map) {
+ VerificationPolicy policy = VerificationPolicy::UNKNOWN;
+ auto manifest_hash = suffix_map.find(packet_hash.first);
if (manifest_hash != suffix_map.end()) {
- CryptoHashType hash_type = manifest_hash->second.first;
- CryptoHash packet_hash = packets[i]->computeDigest(hash_type);
-
- if (!CryptoHash::compareBinaryDigest(
- packet_hash.getDigest<uint8_t>().data(),
- manifest_hash->second.second.data(), hash_type)) {
- policies[i] = VerificationPolicy::ABORT;
- } else {
- policies[i] = VerificationPolicy::ACCEPT;
+ policy = VerificationPolicy::ABORT;
+
+ if (packet_hash.second == manifest_hash->second) {
+ policy = VerificationPolicy::ACCEPT;
}
}
- callVerificationFailedCallback(packets[i], policies[i]);
+ policies[packet_hash.first] = policy;
}
return policies;
}
-void Verifier::addKey(PARCKey *key) { parcVerifier_AddKey(verifier_, key); }
+Verifier::PolicyMap Verifier::verifyPackets(const vector<PacketPtr> &packets,
+ const SuffixMap &suffix_map) {
+ PolicyMap policies;
+
+ for (const auto &packet : packets) {
+ Suffix suffix = packet->getName().getSuffix();
+ VerificationPolicy policy = VerificationPolicy::UNKNOWN;
+ auto manifest_hash = suffix_map.find(suffix);
+
+ if (manifest_hash != suffix_map.end()) {
+ policy = VerificationPolicy::ABORT;
+ CryptoHashType hash_type = manifest_hash->second.getType();
+ CryptoHash packet_hash = packet->computeDigest(hash_type);
+
+ if (packet_hash == manifest_hash->second) {
+ policy = VerificationPolicy::ACCEPT;
+ }
+ }
-void Verifier::setHasher(PARCCryptoHasher *hasher) {
- parcAssertNotNull(hasher, "Expected non-null hasher");
- if (hasher_) parcCryptoHasher_Release(&hasher_);
- hasher_ = parcCryptoHasher_Acquire(hasher);
+ policies[suffix] = policy;
+ callVerificationFailedCallback(packet, policy);
+ }
+
+ return policies;
}
void Verifier::setVerificationFailedCallback(
@@ -192,27 +149,6 @@ void Verifier::getVerificationFailedCallback(
*verfication_failed_cb = &verification_failed_cb_;
}
-size_t Verifier::getSignatureSize(const PacketPtr packet) {
- return packet->getSignatureSize();
-}
-
-CryptoHash Verifier::computeHash(PacketPtr packet) {
- parcAssertNotNull(hasher_, "Expected non-null hasher");
-
- CryptoHasher crypto_hasher(hasher_);
- const utils::MemBuf &header_chain = *packet;
- const utils::MemBuf *current = &header_chain;
-
- crypto_hasher.init();
-
- do {
- crypto_hasher.updateBytes(current->data(), current->length());
- current = current->next();
- } while (current != &header_chain);
-
- return crypto_hasher.finalize();
-}
-
void Verifier::callVerificationFailedCallback(PacketPtr packet,
VerificationPolicy &policy) {
if (verification_failed_cb_ == interface::VOID_HANDLER) {
@@ -228,107 +164,222 @@ void Verifier::callVerificationFailedCallback(PacketPtr packet,
}
}
+// ---------------------------------------------------------
+// Void Verifier
+// ---------------------------------------------------------
bool VoidVerifier::verifyPacket(PacketPtr packet) { return true; }
-vector<VerificationPolicy> VoidVerifier::verifyPackets(
+bool VoidVerifier::verifyBuffer(const vector<uint8_t> &buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ return true;
+}
+
+bool VoidVerifier::verifyBuffer(const utils::MemBuf *buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ return true;
+}
+
+Verifier::PolicyMap VoidVerifier::verifyPackets(
const vector<PacketPtr> &packets) {
- return vector<VerificationPolicy>(packets.size(), VerificationPolicy::ACCEPT);
+ PolicyMap policies;
+
+ for (const auto &packet : packets) {
+ policies[packet->getName().getSuffix()] = VerificationPolicy::ACCEPT;
+ }
+
+ return policies;
}
-vector<VerificationPolicy> VoidVerifier::verifyPackets(
- const vector<PacketPtr> &packets,
- const unordered_map<Suffix, HashEntry> &suffix_map) {
- return vector<VerificationPolicy>(packets.size(), VerificationPolicy::ACCEPT);
+Verifier::PolicyMap VoidVerifier::verifyPackets(
+ const vector<PacketPtr> &packets, const SuffixMap &suffix_map) {
+ return verifyPackets(packets);
}
-AsymmetricVerifier::AsymmetricVerifier(PARCKey *pub_key) { addKey(pub_key); }
+// ---------------------------------------------------------
+// Asymmetric Verifier
+// ---------------------------------------------------------
+AsymmetricVerifier::AsymmetricVerifier(shared_ptr<EVP_PKEY> key) {
+ setKey(key);
+}
AsymmetricVerifier::AsymmetricVerifier(const string &cert_path) {
- setCertificate(cert_path);
+ useCertificate(cert_path);
+}
+
+AsymmetricVerifier::AsymmetricVerifier(shared_ptr<X509> cert) {
+ useCertificate(cert);
}
-void AsymmetricVerifier::setCertificate(const string &cert_path) {
- PARCCertificateFactory *factory = parcCertificateFactory_Create(
- PARCCertificateType_X509, PARCContainerEncoding_PEM);
+void AsymmetricVerifier::setKey(shared_ptr<EVP_PKEY> key) { key_ = key; };
- struct stat buffer;
- if (stat(cert_path.c_str(), &buffer) != 0) {
- throw errors::RuntimeException("Certificate does not exist");
+void AsymmetricVerifier::useCertificate(const string &cert_path) {
+ FILE *certf = fopen(cert_path.c_str(), "rb");
+
+ if (certf == nullptr) {
+ throw errors::RuntimeException("Certificate not found");
}
- PARCCertificate *certificate =
- parcCertificateFactory_CreateCertificateFromFile(factory,
- cert_path.c_str(), NULL);
- PARCKey *key = parcCertificate_GetPublicKey(certificate);
+ shared_ptr<X509> cert = shared_ptr<X509>(
+ PEM_read_X509(certf, nullptr, nullptr, nullptr), ::X509_free);
+ useCertificate(cert);
- addKey(key);
+ fclose(certf);
+}
- parcKey_Release(&key);
- parcCertificateFactory_Release(&factory);
+void AsymmetricVerifier::useCertificate(shared_ptr<X509> cert) {
+ key_ = shared_ptr<EVP_PKEY>(X509_get_pubkey(cert.get()), ::EVP_PKEY_free);
}
-SymmetricVerifier::SymmetricVerifier(const string &passphrase)
- : passphrase_(nullptr), signer_(nullptr) {
- setPassphrase(passphrase);
+bool AsymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
+
+ if (EVP_DigestVerifyInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ if (EVP_DigestVerifyUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
+
+ return EVP_DigestVerifyFinal(mdctx.get(), signature.data(),
+ signature.size()) == 1;
+}
+
+bool AsymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ const utils::MemBuf *p = buffer;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
+
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
+
+ if (EVP_DigestVerifyInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestVerifyUpdate(mdctx.get(), p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
+
+ p = p->next();
+ } while (p != buffer);
+
+ return EVP_DigestVerifyFinal(mdctx.get(), signature.data(),
+ signature.size()) == 1;
}
-SymmetricVerifier::~SymmetricVerifier() {
- if (passphrase_) parcBuffer_Release(&passphrase_);
- if (signer_) parcSigner_Release(&signer_);
+// ---------------------------------------------------------
+// Symmetric Verifier
+// ---------------------------------------------------------
+SymmetricVerifier::SymmetricVerifier(const string &passphrase) {
+ setPassphrase(passphrase);
}
+// Create and set a symmetric key from a passphrase.
void SymmetricVerifier::setPassphrase(const string &passphrase) {
- if (passphrase_) parcBuffer_Release(&passphrase_);
-
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_PutString(composer, passphrase.c_str());
- passphrase_ = parcBufferComposer_ProduceBuffer(composer);
- parcBufferComposer_Release(&composer);
+ key_ = shared_ptr<EVP_PKEY>(
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, nullptr,
+ (const unsigned char *)passphrase.c_str(),
+ passphrase.size()),
+ EVP_PKEY_free);
}
-void SymmetricVerifier::setSigner(const PARCCryptoSuite &suite) {
- parcAssertNotNull(passphrase_, "Expected non-null passphrase");
+bool SymmetricVerifier::verifyBuffer(const vector<uint8_t> &buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
- if (signer_) parcSigner_Release(&signer_);
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
+
+ vector<uint8_t> signature_bis(signature.size());
+ size_t signature_bis_len;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
- PARCSymmetricKeyStore *key_store = parcSymmetricKeyStore_Create(passphrase_);
- PARCSymmetricKeySigner *key_signer = parcSymmetricKeySigner_Create(
- key_store, parcCryptoSuite_GetCryptoHash(suite));
- signer_ = parcSigner_Create(key_signer, PARCSymmetricKeySignerAsSigner);
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
- PARCKeyId *key_id = parcSigner_CreateKeyId(signer_);
- PARCKey *key = parcKey_CreateFromSymmetricKey(
- key_id, parcSigner_GetSigningAlgorithm(signer_), passphrase_);
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
- addKey(key);
- setHasher(parcSigner_GetCryptoHasher(signer_));
+ if (EVP_DigestSignUpdate(mdctx.get(), buffer.data(), buffer.size()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
+ }
- parcSymmetricKeyStore_Release(&key_store);
- parcSymmetricKeySigner_Release(&key_signer);
- parcKeyId_Release(&key_id);
- parcKey_Release(&key);
+ if (EVP_DigestSignFinal(mdctx.get(), signature_bis.data(),
+ &signature_bis_len) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
+ }
+
+ return signature == signature_bis && signature.size() == signature_bis_len;
}
-vector<VerificationPolicy> SymmetricVerifier::verifyPackets(
- const vector<PacketPtr> &packets) {
- vector<VerificationPolicy> policies(packets.size(), VerificationPolicy::DROP);
+bool SymmetricVerifier::verifyBuffer(const utils::MemBuf *buffer,
+ const vector<uint8_t> &signature,
+ CryptoHashType hash_type) {
+ CryptoHashEVP hash_evp = CryptoHash::getEVP(hash_type);
+
+ if (hash_evp == nullptr) {
+ throw errors::RuntimeException("Unknown hash type");
+ }
- for (unsigned int i = 0; i < packets.size(); ++i) {
- auto suite =
- static_cast<PARCCryptoSuite>(packets[i]->getValidationAlgorithm());
+ const utils::MemBuf *p = buffer;
+ vector<uint8_t> signature_bis(signature.size());
+ size_t signature_bis_len;
+ shared_ptr<EVP_MD_CTX> mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_free);
- if (!signer_ || suite != parcSigner_GetCryptoSuite(signer_)) {
- setSigner(suite);
- }
+ if (mdctx == nullptr) {
+ throw errors::RuntimeException("Digest context allocation failed");
+ }
- if (verifyPacket(packets[i])) {
- policies[i] = VerificationPolicy::ACCEPT;
+ if (EVP_DigestSignInit(mdctx.get(), nullptr, (*hash_evp)(), nullptr,
+ key_.get()) != 1) {
+ throw errors::RuntimeException("Digest initialization failed");
+ }
+
+ do {
+ if (EVP_DigestSignUpdate(mdctx.get(), p->data(), p->length()) != 1) {
+ throw errors::RuntimeException("Digest update failed");
}
- callVerificationFailedCallback(packets[i], policies[i]);
+ p = p->next();
+ } while (p != buffer);
+
+ if (EVP_DigestSignFinal(mdctx.get(), signature_bis.data(),
+ &signature_bis_len) != 1) {
+ throw errors::RuntimeException("Digest computation failed");
}
- return policies;
+ return signature == signature_bis && signature.size() == signature_bis_len;
}
} // namespace auth
diff --git a/libtransport/src/config.h.in b/libtransport/src/config.h.in
index ef47affda..73a326a84 100644
--- a/libtransport/src/config.h.in
+++ b/libtransport/src/config.h.in
@@ -26,5 +26,6 @@
#endif
#define RAAQM_CONFIG_PATH "@raaqm_config_path@"
+#define ENABLE_RELY @ENABLE_RELY@
#cmakedefine __vpp__
diff --git a/libtransport/src/core/CMakeLists.txt b/libtransport/src/core/CMakeLists.txt
index 4e3ac10ec..e442bb863 100644
--- a/libtransport/src/core/CMakeLists.txt
+++ b/libtransport/src/core/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/facade.h
${CMAKE_CURRENT_SOURCE_DIR}/manifest.h
@@ -24,7 +22,6 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/errors.h
${CMAKE_CURRENT_SOURCE_DIR}/global_configuration.h
${CMAKE_CURRENT_SOURCE_DIR}/local_connector.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rs.h
)
list(APPEND SOURCE_FILES
@@ -39,8 +36,6 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/global_configuration.cc
${CMAKE_CURRENT_SOURCE_DIR}/io_module.cc
${CMAKE_CURRENT_SOURCE_DIR}/local_connector.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/fec.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/rs.cc
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/core/connector.cc b/libtransport/src/core/connector.cc
deleted file mode 100644
index 63919537d..000000000
--- a/libtransport/src/core/connector.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <core/connector.h>
-
-namespace transport {
-
-namespace core {
-
-std::once_flag Connector::init_flag_;
-
-Connector::Connector(PacketReceivedCallback &&receive_callback,
- OnReconnect &&reconnect_callback)
- : packet_pool_(),
- receive_callback_(std::move(receive_callback)),
- on_reconnect_callback_(std::move(reconnect_callback)),
- state_(ConnectorState::CLOSED) {
- init();
-}
-
-void Connector::init() { increasePoolSize(); }
-
-void Connector::increasePoolSize(std::size_t size) {
- // Allocate space for receiving packets
- const auto capacity = packet_size * size;
- uint8_t *buffer = static_cast<uint8_t *>(malloc(capacity));
- std::unique_ptr<utils::MemBuf> buffer0 =
- utils::MemBuf::takeOwnership(buffer, capacity, 0, nullptr, nullptr, true);
-
- for (std::size_t i = 1; i < size; i++) {
- auto b = buffer0->cloneOne();
- b->advance(i * packet_size);
- packet_pool_.add(b.release());
- }
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/core/connector.h b/libtransport/src/core/connector.h
deleted file mode 100644
index f2bbe5dcd..000000000
--- a/libtransport/src/core/connector.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/core/packet.h>
-#include <hicn/transport/utils/membuf.h>
-#include <hicn/transport/utils/object_pool.h>
-#include <hicn/transport/utils/ring_buffer.h>
-
-#include <deque>
-#include <functional>
-
-namespace transport {
-
-namespace core {
-
-enum class ConnectorType : uint8_t {
- SOCKET_CONNECTOR,
- RAW_SOCKET_CONNECTOR,
- VPP_CONNECTOR,
-};
-
-class Connector {
- protected:
- enum class ConnectorState {
- CLOSED,
- CONNECTING,
- CONNECTED,
- };
-
- public:
- static constexpr std::size_t packet_size = 2048;
- static constexpr std::size_t queue_size = 4096;
- static constexpr std::size_t packet_pool_size = 4096;
-
- using PacketRing = utils::CircularFifo<Packet::MemBufPtr, queue_size>;
- using PacketQueue = std::deque<Packet::MemBufPtr>;
- using PacketReceivedCallback = std::function<void(Packet::MemBufPtr &&)>;
- using OnReconnect = std::function<void()>;
- using PacketSentCallback = std::function<void()>;
-
- Connector(PacketReceivedCallback &&receive_callback,
- OnReconnect &&reconnect_callback);
-
- virtual ~Connector(){};
-
- virtual void send(const Packet::MemBufPtr &packet) = 0;
-
- virtual void send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent = 0) = 0;
-
- virtual void close() = 0;
-
- virtual ConnectorState state() { return state_; };
-
- virtual bool isConnected() { return state_ == ConnectorState::CONNECTED; }
-
- protected:
- void increasePoolSize(std::size_t size = packet_pool_size);
-
- TRANSPORT_ALWAYS_INLINE utils::ObjectPool<utils::MemBuf>::Ptr getPacket() {
- auto result = packet_pool_.get();
-
- while (TRANSPORT_EXPECT_FALSE(!result.first)) {
- // Add packets to the pool
- increasePoolSize();
- result = packet_pool_.get();
- }
-
- if (result.second->isChained()) {
- result.second->separateChain(result.second->next(),
- result.second->prev());
- }
-
- result.second->trimEnd(result.second->length());
- return std::move(result.second);
- }
-
- private:
- void init();
-
- protected:
- static std::once_flag init_flag_;
- utils::ObjectPool<utils::MemBuf> packet_pool_;
- PacketQueue output_buffer_;
-
- // Connector events
- PacketReceivedCallback receive_callback_;
- OnReconnect on_reconnect_callback_;
-
- // Connector state
- ConnectorState state_;
-};
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/core/content_object.cc b/libtransport/src/core/content_object.cc
index 0c68ef559..411494fdf 100644
--- a/libtransport/src/core/content_object.cc
+++ b/libtransport/src/core/content_object.cc
@@ -104,19 +104,6 @@ void ContentObject::setName(const Name &name) {
}
}
-void ContentObject::setName(Name &&name) {
- if (hicn_data_set_name(format_, packet_start_, name.getStructReference()) <
- 0) {
- throw errors::RuntimeException(
- "Error getting the payload length from content object.");
- }
-
- if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
- 0) {
- throw errors::MalformedPacketException();
- }
-}
-
uint32_t ContentObject::getPathLabel() const {
uint32_t path_label;
if (hicn_data_get_path_label(packet_start_, &path_label) < 0) {
diff --git a/libtransport/src/core/fec.cc b/libtransport/src/core/fec.cc
deleted file mode 100644
index 0ce9625a2..000000000
--- a/libtransport/src/core/fec.cc
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * fec.c -- forward error correction based on Vandermonde matrices
- * 980624
- * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
- *
- * Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
- * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
- * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
-
-/*
- * The following parameter defines how many bits are used for
- * field elements. The code supports any value from 2 to 16
- * but fastest operation is achieved with 8 bit elements
- * This is the only parameter you may want to change.
- */
-#ifndef GF_BITS
-#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <hicn/transport/portability/platform.h>
-#include "fec.h"
-
-/**
- * XXX This disable a warning raising only in some platforms.
- * TODO Check if this warning is a mistake or it is a real bug:
- * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83404
- * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=88059
- */
-#ifndef __clang__
-#ifndef _WIN32
-#pragma GCC diagnostic ignored "-Wstringop-overflow"
-#endif
-#endif
-
-/*
- * compatibility stuff
- */
-#if defined (MSDOS) || defined (_WIN32) /* but also for others, e.g. sun... */
-#define NEED_BCOPY
-#define bcmp(a,b,n) memcmp(a,b,n)
-#endif
-
-#ifdef ANDROID
-#define bcmp(a,b,n) memcmp(a,b,n)
-#endif
-
-#ifdef NEED_BCOPY
-#define bcopy(s, d, siz) memcpy((d), (s), (siz))
-#define bzero(d, siz) memset((d), '\0', (siz))
-#endif
-
-/*
- * stuff used for testing purposes only
- */
-
-#ifdef TEST
-#define DEB(x)
-#define DDB(x) x
-#define DEBUG 0 /* minimal debugging */
-#ifdef MSDOS
-#include <time.h>
-struct timeval {
- unsigned long ticks;
-};
-#define gettimeofday(x, dummy) { (x)->ticks = clock() ; }
-#define DIFF_T(a,b) (1+ 1000000*(a.ticks - b.ticks) / CLOCKS_PER_SEC )
-typedef unsigned long u_long ;
-typedef unsigned short u_short ;
-#else /* typically, unix systems */
-#include <sys/time.h>
-#define DIFF_T(a,b) \
- (1+ 1000000*(a.tv_sec - b.tv_sec) + (a.tv_usec - b.tv_usec) )
-#endif
-
-#define TICK(t) \
- {struct timeval x ; \
- gettimeofday(&x, NULL) ; \
- t = x.tv_usec + 1000000* (x.tv_sec & 0xff ) ; \
- }
-#define TOCK(t) \
- { u_long t1 ; TICK(t1) ; \
- if (t1 < t) t = 256000000 + t1 - t ; \
- else t = t1 - t ; \
- if (t == 0) t = 1 ;}
-
-u_long ticks[10]; /* vars for timekeeping */
-#else
-#define DEB(x)
-#define DDB(x)
-#define TICK(x)
-#define TOCK(x)
-#endif /* TEST */
-
-/*
- * You should not need to change anything beyond this point.
- * The first part of the file implements linear algebra in GF.
- *
- * gf is the type used to store an element of the Galois Field.
- * Must constain at least GF_BITS bits.
- *
- * Note: unsigned char will work up to GF(256) but int seems to run
- * faster on the Pentium. We use int whenever have to deal with an
- * index, since they are generally faster.
- */
-#if (GF_BITS < 2 && GF_BITS >16)
-#error "GF_BITS must be 2 .. 16"
-#endif
-
-
-#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */
-
-/*
- * Primitive polynomials - see Lin & Costello, Appendix A,
- * and Lee & Messerschmitt, p. 453.
- */
-static const char *allPp[] = { /* GF_BITS polynomial */
- NULL, /* 0 no code */
- NULL, /* 1 no code */
- "111", /* 2 1+x+x^2 */
- "1101", /* 3 1+x+x^3 */
- "11001", /* 4 1+x+x^4 */
- "101001", /* 5 1+x^2+x^5 */
- "1100001", /* 6 1+x+x^6 */
- "10010001", /* 7 1 + x^3 + x^7 */
- "101110001", /* 8 1+x^2+x^3+x^4+x^8 */
- "1000100001", /* 9 1+x^4+x^9 */
- "10010000001", /* 10 1+x^3+x^10 */
- "101000000001", /* 11 1+x^2+x^11 */
- "1100101000001", /* 12 1+x+x^4+x^6+x^12 */
- "11011000000001", /* 13 1+x+x^3+x^4+x^13 */
- "110000100010001", /* 14 1+x+x^6+x^10+x^14 */
- "1100000000000001", /* 15 1+x+x^15 */
- "11010000000010001" /* 16 1+x+x^3+x^12+x^16 */
-};
-
-
-/*
- * To speed up computations, we have tables for logarithm, exponent
- * and inverse of a number. If GF_BITS <= 8, we use a table for
- * multiplication as well (it takes 64K, no big deal even on a PDA,
- * especially because it can be pre-initialized an put into a ROM!),
- * otherwhise we use a table of logarithms.
- * In any case the macro gf_mul(x,y) takes care of multiplications.
- */
-
-static gf gf_exp[2*GF_SIZE]; /* index->poly form conversion table */
-static int gf_log[GF_SIZE + 1]; /* Poly->index form conversion table */
-static gf inverse[GF_SIZE+1]; /* inverse of field elem. */
- /* inv[\alpha**i]=\alpha**(GF_SIZE-i-1) */
-
-/*
- * modnn(x) computes x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1,
- * without a slow divide.
- */
-static inline gf
-modnn(int x)
-{
- while (x >= GF_SIZE) {
- x -= GF_SIZE;
- x = (x >> GF_BITS) + (x & GF_SIZE);
- }
- return x;
-}
-
-#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;}
-
-/*
- * gf_mul(x,y) multiplies two numbers. If GF_BITS<=8, it is much
- * faster to use a multiplication table.
- *
- * USE_GF_MULC, GF_MULC0(c) and GF_ADDMULC(x) can be used when multiplying
- * many numbers by the same constant. In this case the first
- * call sets the constant, and others perform the multiplications.
- * A value related to the multiplication is held in a local variable
- * declared with USE_GF_MULC . See usage in addmul1().
- */
-#if (GF_BITS <= 8)
-static gf gf_mul_table[GF_SIZE + 1][GF_SIZE + 1];
-
-#define gf_mul(x,y) gf_mul_table[x][y]
-
-#define USE_GF_MULC gf * __gf_mulc_
-#define GF_MULC0(c) __gf_mulc_ = gf_mul_table[c]
-#define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x]
-
-static void
-init_mul_table()
-{
- int i, j;
- for (i=0; i< GF_SIZE+1; i++)
- for (j=0; j< GF_SIZE+1; j++)
- gf_mul_table[i][j] = gf_exp[modnn(gf_log[i] + gf_log[j]) ] ;
-
- for (j=0; j< GF_SIZE+1; j++)
- gf_mul_table[0][j] = gf_mul_table[j][0] = 0;
-}
-#else /* GF_BITS > 8 */
-static inline gf
-gf_mul(x,y)
-{
- if ( (x) == 0 || (y)==0 ) return 0;
-
- return gf_exp[gf_log[x] + gf_log[y] ] ;
-}
-#define init_mul_table()
-
-#define USE_GF_MULC register gf * __gf_mulc_
-#define GF_MULC0(c) __gf_mulc_ = &gf_exp[ gf_log[c] ]
-#define GF_ADDMULC(dst, x) { if (x) dst ^= __gf_mulc_[ gf_log[x] ] ; }
-#endif
-
-/*
- * Generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
- * Lookup tables:
- * index->polynomial form gf_exp[] contains j= \alpha^i;
- * polynomial form -> index form gf_log[ j = \alpha^i ] = i
- * \alpha=x is the primitive element of GF(2^m)
- *
- * For efficiency, gf_exp[] has size 2*GF_SIZE, so that a simple
- * multiplication of two numbers can be resolved without calling modnn
- */
-
-/*
- * i use malloc so many times, it is easier to put checks all in
- * one place.
- */
-static void *
-my_malloc(int sz, const char *err_string)
-{
- void *p = malloc( sz );
- if (p == NULL) {
- fprintf(stderr, "-- malloc failure allocating %s\n", err_string);
- exit(1) ;
- }
- return p ;
-}
-
-#define NEW_GF_MATRIX(rows, cols) \
- (gf *)my_malloc(rows * cols * sizeof(gf), " ## __LINE__ ## " )
-
-/*
- * initialize the data structures used for computations in GF.
- */
-static void
-generate_gf(void)
-{
- int i;
- gf mask;
- const char *Pp = allPp[GF_BITS] ;
-
- mask = 1; /* x ** 0 = 1 */
- gf_exp[GF_BITS] = 0; /* will be updated at the end of the 1st loop */
- /*
- * first, generate the (polynomial representation of) powers of \alpha,
- * which are stored in gf_exp[i] = \alpha ** i .
- * At the same time build gf_log[gf_exp[i]] = i .
- * The first GF_BITS powers are simply bits shifted to the left.
- */
- for (i = 0; i < GF_BITS; i++, mask <<= 1 ) {
- gf_exp[i] = mask;
- gf_log[gf_exp[i]] = i;
- /*
- * If Pp[i] == 1 then \alpha ** i occurs in poly-repr
- * gf_exp[GF_BITS] = \alpha ** GF_BITS
- */
- if ( Pp[i] == '1' )
- gf_exp[GF_BITS] ^= mask;
- }
- /*
- * now gf_exp[GF_BITS] = \alpha ** GF_BITS is complete, so can als
- * compute its inverse.
- */
- gf_log[gf_exp[GF_BITS]] = GF_BITS;
- /*
- * Poly-repr of \alpha ** (i+1) is given by poly-repr of
- * \alpha ** i shifted left one-bit and accounting for any
- * \alpha ** GF_BITS term that may occur when poly-repr of
- * \alpha ** i is shifted.
- */
- mask = 1 << (GF_BITS - 1 ) ;
- for (i = GF_BITS + 1; i < GF_SIZE; i++) {
- if (gf_exp[i - 1] >= mask)
- gf_exp[i] = gf_exp[GF_BITS] ^ ((gf_exp[i - 1] ^ mask) << 1);
- else
- gf_exp[i] = gf_exp[i - 1] << 1;
- gf_log[gf_exp[i]] = i;
- }
- /*
- * log(0) is not defined, so use a special value
- */
- gf_log[0] = GF_SIZE ;
- /* set the extended gf_exp values for fast multiply */
- for (i = 0 ; i < GF_SIZE ; i++)
- gf_exp[i + GF_SIZE] = gf_exp[i] ;
-
- /*
- * again special cases. 0 has no inverse. This used to
- * be initialized to GF_SIZE, but it should make no difference
- * since noone is supposed to read from here.
- */
- inverse[0] = 0 ;
- inverse[1] = 1;
- for (i=2; i<=GF_SIZE; i++)
- inverse[i] = gf_exp[GF_SIZE-gf_log[i]];
-}
-
-/*
- * Various linear algebra operations that i use often.
- */
-
-/*
- * addmul() computes dst[] = dst[] + c * src[]
- * This is used often, so better optimize it! Currently the loop is
- * unrolled 16 times, a good value for 486 and pentium-class machines.
- * The case c=0 is also optimized, whereas c=1 is not. These
- * calls are unfrequent in my typical apps so I did not bother.
- *
- * Note that gcc on
- */
-#define addmul(dst, src, c, sz) \
- if (c != 0) addmul1(dst, src, c, sz)
-
-#define UNROLL 16 /* 1, 4, 8, 16 */
-static void
-addmul1(gf *dst1, gf *src1, gf c, int sz)
-{
- USE_GF_MULC ;
- gf *dst = dst1, *src = src1 ;
- gf *lim = &dst[sz - UNROLL + 1] ;
-
- GF_MULC0(c) ;
-
-#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */
- for (; dst < lim ; dst += UNROLL, src += UNROLL ) {
- GF_ADDMULC( dst[0] , src[0] );
- GF_ADDMULC( dst[1] , src[1] );
- GF_ADDMULC( dst[2] , src[2] );
- GF_ADDMULC( dst[3] , src[3] );
-#if (UNROLL > 4)
- GF_ADDMULC( dst[4] , src[4] );
- GF_ADDMULC( dst[5] , src[5] );
- GF_ADDMULC( dst[6] , src[6] );
- GF_ADDMULC( dst[7] , src[7] );
-#endif
-#if (UNROLL > 8)
- GF_ADDMULC( dst[8] , src[8] );
- GF_ADDMULC( dst[9] , src[9] );
- GF_ADDMULC( dst[10] , src[10] );
- GF_ADDMULC( dst[11] , src[11] );
- GF_ADDMULC( dst[12] , src[12] );
- GF_ADDMULC( dst[13] , src[13] );
- GF_ADDMULC( dst[14] , src[14] );
- GF_ADDMULC( dst[15] , src[15] );
-#endif
- }
-#endif
- lim += UNROLL - 1 ;
- for (; dst < lim; dst++, src++ ) /* final components */
- GF_ADDMULC( *dst , *src );
-}
-
-/*
- * computes C = AB where A is n*k, B is k*m, C is n*m
- */
-static void
-matmul(gf *a, gf *b, gf *c, int n, int k, int m)
-{
- int row, col, i ;
-
- for (row = 0; row < n ; row++) {
- for (col = 0; col < m ; col++) {
- gf *pa = &a[ row * k ];
- gf *pb = &b[ col ];
- gf acc = 0 ;
- for (i = 0; i < k ; i++, pa++, pb += m )
- acc ^= gf_mul( *pa, *pb ) ;
- c[ row * m + col ] = acc ;
- }
- }
-}
-
-#ifdef DEBUGG
-/*
- * returns 1 if the square matrix is identiy
- * (only for test)
- */
-static int
-is_identity(gf *m, int k)
-{
- int row, col ;
- for (row=0; row<k; row++)
- for (col=0; col<k; col++)
- if ( (row==col && *m != 1) ||
- (row!=col && *m != 0) )
- return 0 ;
- else
- m++ ;
- return 1 ;
-}
-#endif /* debug */
-
-/*
- * invert_mat() takes a matrix and produces its inverse
- * k is the size of the matrix.
- * (Gauss-Jordan, adapted from Numerical Recipes in C)
- * Return non-zero if singular.
- */
-DEB( int pivloops=0; int pivswaps=0 ; /* diagnostic */)
-static int
-invert_mat(gf *src, int k)
-{
- gf c, *p ;
- int irow, icol, row, col, i, ix ;
-
- int error = 1 ;
- int *indxc = (int*)my_malloc(k*sizeof(int), "indxc");
- int *indxr = (int*)my_malloc(k*sizeof(int), "indxr");
- int *ipiv = (int*)my_malloc(k*sizeof(int), "ipiv");
- gf *id_row = NEW_GF_MATRIX(1, k);
- gf *temp_row = NEW_GF_MATRIX(1, k);
-
- bzero(id_row, k*sizeof(gf));
- DEB( pivloops=0; pivswaps=0 ; /* diagnostic */ )
- /*
- * ipiv marks elements already used as pivots.
- */
- for (i = 0; i < k ; i++)
- ipiv[i] = 0 ;
-
- for (col = 0; col < k ; col++) {
- gf *pivot_row ;
- /*
- * Zeroing column 'col', look for a non-zero element.
- * First try on the diagonal, if it fails, look elsewhere.
- */
- irow = icol = -1 ;
- if (ipiv[col] != 1 && src[col*k + col] != 0) {
- irow = col ;
- icol = col ;
- goto found_piv ;
- }
- for (row = 0 ; row < k ; row++) {
- if (ipiv[row] != 1) {
- for (ix = 0 ; ix < k ; ix++) {
- DEB( pivloops++ ; )
- if (ipiv[ix] == 0) {
- if (src[row*k + ix] != 0) {
- irow = row ;
- icol = ix ;
- goto found_piv ;
- }
- } else if (ipiv[ix] > 1) {
- fprintf(stderr, "singular matrix\n");
- goto fail ;
- }
- }
- }
- }
- if (icol == -1) {
- fprintf(stderr, "XXX pivot not found!\n");
- goto fail ;
- }
-found_piv:
- ++(ipiv[icol]) ;
- /*
- * swap rows irow and icol, so afterwards the diagonal
- * element will be correct. Rarely done, not worth
- * optimizing.
- */
- if (irow != icol) {
- for (ix = 0 ; ix < k ; ix++ ) {
- SWAP( src[irow*k + ix], src[icol*k + ix], gf) ;
- }
- }
- indxr[col] = irow ;
- indxc[col] = icol ;
- pivot_row = &src[icol*k] ;
- c = pivot_row[icol] ;
- if (c == 0) {
- fprintf(stderr, "singular matrix 2\n");
- goto fail ;
- }
- if (c != 1 ) { /* otherwhise this is a NOP */
- /*
- * this is done often , but optimizing is not so
- * fruitful, at least in the obvious ways (unrolling)
- */
- DEB( pivswaps++ ; )
- c = inverse[ c ] ;
- pivot_row[icol] = 1 ;
- for (ix = 0 ; ix < k ; ix++ )
- pivot_row[ix] = gf_mul(c, pivot_row[ix] );
- }
- /*
- * from all rows, remove multiples of the selected row
- * to zero the relevant entry (in fact, the entry is not zero
- * because we know it must be zero).
- * (Here, if we know that the pivot_row is the identity,
- * we can optimize the addmul).
- */
- id_row[icol] = 1;
- if (bcmp(pivot_row, id_row, k*sizeof(gf)) != 0) {
- for (p = src, ix = 0 ; ix < k ; ix++, p += k ) {
- if (ix != icol) {
- c = p[icol] ;
- p[icol] = 0 ;
- addmul(p, pivot_row, c, k );
- }
- }
- }
- id_row[icol] = 0;
- } /* done all columns */
- for (col = k-1 ; col >= 0 ; col-- ) {
- if (indxr[col] <0 || indxr[col] >= k)
- fprintf(stderr, "AARGH, indxr[col] %d\n", indxr[col]);
- else if (indxc[col] <0 || indxc[col] >= k)
- fprintf(stderr, "AARGH, indxc[col] %d\n", indxc[col]);
- else
- if (indxr[col] != indxc[col] ) {
- for (row = 0 ; row < k ; row++ ) {
- SWAP( src[row*k + indxr[col]], src[row*k + indxc[col]], gf) ;
- }
- }
- }
- error = 0 ;
-fail:
- free(indxc);
- free(indxr);
- free(ipiv);
- free(id_row);
- free(temp_row);
- return error ;
-}
-
-/*
- * fast code for inverting a vandermonde matrix.
- * XXX NOTE: It assumes that the matrix
- * is not singular and _IS_ a vandermonde matrix. Only uses
- * the second column of the matrix, containing the p_i's.
- *
- * Algorithm borrowed from "Numerical recipes in C" -- sec.2.8, but
- * largely revised for my purposes.
- * p = coefficients of the matrix (p_i)
- * q = values of the polynomial (known)
- */
-
-int
-invert_vdm(gf *src, int k)
-{
- int i, j, row, col ;
- gf *b, *c, *p;
- gf t, xx ;
-
- if (k == 1) /* degenerate case, matrix must be p^0 = 1 */
- return 0 ;
- /*
- * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1
- * b holds the coefficient for the matrix inversion
- */
- c = NEW_GF_MATRIX(1, k);
- b = NEW_GF_MATRIX(1, k);
-
- p = NEW_GF_MATRIX(1, k);
-
- for ( j=1, i = 0 ; i < k ; i++, j+=k ) {
- c[i] = 0 ;
- p[i] = src[j] ; /* p[i] */
- }
- /*
- * construct coeffs. recursively. We know c[k] = 1 (implicit)
- * and start P_0 = x - p_0, then at each stage multiply by
- * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1}
- * After k steps we are done.
- */
- c[k-1] = p[0] ; /* really -p(0), but x = -x in GF(2^m) */
- for (i = 1 ; i < k ; i++ ) {
- gf p_i = p[i] ; /* see above comment */
- for (j = k-1 - ( i - 1 ) ; j < k-1 ; j++ )
- c[j] ^= gf_mul( p_i, c[j+1] ) ;
- c[k-1] ^= p_i ;
- }
-
- for (row = 0 ; row < k ; row++ ) {
- /*
- * synthetic division etc.
- */
- xx = p[row] ;
- t = 1 ;
- b[k-1] = 1 ; /* this is in fact c[k] */
- for (i = k-2 ; i >= 0 ; i-- ) {
- b[i] = c[i+1] ^ gf_mul(xx, b[i+1]) ;
- t = gf_mul(xx, t) ^ b[i] ;
- }
- for (col = 0 ; col < k ; col++ )
- src[col*k + row] = gf_mul(inverse[t], b[col] );
- }
- free(c) ;
- free(b) ;
- free(p) ;
- return 0 ;
-}
-
-static int fec_initialized = 0 ;
-static void
-init_fec()
-{
- TICK(ticks[0]);
- generate_gf();
- TOCK(ticks[0]);
- DDB(fprintf(stderr, "generate_gf took %ldus\n", ticks[0]);)
- TICK(ticks[0]);
- init_mul_table();
- TOCK(ticks[0]);
- DDB(fprintf(stderr, "init_mul_table took %ldus\n", ticks[0]);)
- fec_initialized = 1 ;
-}
-
-/*
- * This section contains the proper FEC encoding/decoding routines.
- * The encoding matrix is computed starting with a Vandermonde matrix,
- * and then transforming it into a systematic matrix.
- */
-
-#define FEC_MAGIC 0xFECC0DEC
-
-void
-fec_free(struct fec_parms *p)
-{
- if (p==NULL ||
- p->magic != ( ( (FEC_MAGIC ^ p->k) ^ p->n) ^ (unsigned long)(p->enc_matrix)) ) {
- fprintf(stderr, "bad parameters to fec_free\n");
- return ;
- }
- free(p->enc_matrix);
- free(p);
-}
-
-/*
- * create a new encoder, returning a descriptor. This contains k,n and
- * the encoding matrix.
- */
-struct fec_parms *
-fec_new(int k, int n)
-{
- int row, col ;
- gf *p, *tmp_m ;
-
- struct fec_parms *retval ;
-
- if (fec_initialized == 0)
- init_fec();
-
- if (k > GF_SIZE + 1 || n > GF_SIZE + 1 || k > n ) {
- fprintf(stderr, "Invalid parameters k %d n %d GF_SIZE %d\n",
- k, n, GF_SIZE );
- return NULL ;
- }
- retval = (struct fec_parms *)my_malloc(sizeof(struct fec_parms), "new_code");
- retval->k = k ;
- retval->n = n ;
- retval->enc_matrix = NEW_GF_MATRIX(n, k);
- retval->magic = ( ( FEC_MAGIC ^ k) ^ n) ^ (unsigned long)(retval->enc_matrix) ;
- tmp_m = NEW_GF_MATRIX(n, k);
- /*
- * fill the matrix with powers of field elements, starting from 0.
- * The first row is special, cannot be computed with exp. table.
- */
- tmp_m[0] = 1 ;
- for (col = 1; col < k ; col++)
- tmp_m[col] = 0 ;
- for (p = tmp_m + k, row = 0; row < n-1 ; row++, p += k) {
- for ( col = 0 ; col < k ; col ++ )
- p[col] = gf_exp[modnn(row*col)];
- }
-
- /*
- * quick code to build systematic matrix: invert the top
- * k*k vandermonde matrix, multiply right the bottom n-k rows
- * by the inverse, and construct the identity matrix at the top.
- */
- TICK(ticks[3]);
- invert_vdm(tmp_m, k); /* much faster than invert_mat */
- matmul(tmp_m + k*k, tmp_m, retval->enc_matrix + k*k, n - k, k, k);
- /*
- * the upper matrix is I so do not bother with a slow multiply
- */
- bzero(retval->enc_matrix, k*k*sizeof(gf) );
- for (p = retval->enc_matrix, col = 0 ; col < k ; col++, p += k+1 )
- *p = 1 ;
- free(tmp_m);
- TOCK(ticks[3]);
-
- DDB(fprintf(stderr, "--- %ld us to build encoding matrix\n",
- ticks[3]);)
- DEB(pr_matrix(retval->enc_matrix, n, k, "encoding_matrix");)
- return retval ;
-}
-
-/*
- * fec_encode accepts as input pointers to n data packets of size sz,
- * and produces as output a packet pointed to by fec, computed
- * with index "index".
- */
-void
-fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz)
-{
- int i, k = code->k ;
- gf *p ;
-
- if (GF_BITS > 8)
- sz /= 2 ;
-
- if (index < k)
- bcopy(src[index], fec, sz*sizeof(gf) ) ;
- else if (index < code->n) {
- p = &(code->enc_matrix[index*k] );
- bzero(fec, sz*sizeof(gf));
- for (i = 0; i < k ; i++)
- addmul(fec, src[i], p[i], sz ) ;
- } else
- fprintf(stderr, "Invalid index %d (max %d)\n",
- index, code->n - 1 );
-}
-
-/*
- * shuffle move src packets in their position
- */
-static int
-shuffle(gf *pkt[], int index[], int k)
-{
- int i;
-
- for ( i = 0 ; i < k ; ) {
- if (index[i] >= k || index[i] == i)
- i++ ;
- else {
- /*
- * put pkt in the right position (first check for conflicts).
- */
- int c = index[i] ;
-
- if (index[c] == c) {
- DEB(fprintf(stderr, "\nshuffle, error at %d\n", i);)
- return 1 ;
- }
- SWAP(index[i], index[c], int) ;
- SWAP(pkt[i], pkt[c], gf *) ;
- }
- }
- DEB( /* just test that it works... */
- for ( i = 0 ; i < k ; i++ ) {
- if (index[i] < k && index[i] != i) {
- fprintf(stderr, "shuffle: after\n");
- for (i=0; i<k ; i++) fprintf(stderr, "%3d ", index[i]);
- fprintf(stderr, "\n");
- return 1 ;
- }
- }
- )
- return 0 ;
-}
-
-/*
- * build_decode_matrix constructs the encoding matrix given the
- * indexes. The matrix must be already allocated as
- * a vector of k*k elements, in row-major order
- */
-static gf *
-build_decode_matrix(struct fec_parms *code, gf *pkt[], int index[])
-{
- int i , k = code->k ;
- gf *p, *matrix = NEW_GF_MATRIX(k, k);
-
- TICK(ticks[9]);
- for (i = 0, p = matrix ; i < k ; i++, p += k ) {
-#if 1 /* this is simply an optimization, not very useful indeed */
- if (index[i] < k) {
- bzero(p, k*sizeof(gf) );
- p[i] = 1 ;
- } else
-#endif
- if (index[i] < code->n )
- bcopy( &(code->enc_matrix[index[i]*k]), p, k*sizeof(gf) );
- else {
- fprintf(stderr, "decode: invalid index %d (max %d)\n",
- index[i], code->n - 1 );
- free(matrix) ;
- return NULL ;
- }
- }
- TICK(ticks[9]);
- if (invert_mat(matrix, k)) {
- free(matrix);
- matrix = NULL ;
- }
- TOCK(ticks[9]);
- return matrix ;
-}
-
-/*
- * fec_decode receives as input a vector of packets, the indexes of
- * packets, and produces the correct vector as output.
- *
- * Input:
- * code: pointer to code descriptor
- * pkt: pointers to received packets. They are modified
- * to store the output packets (in place)
- * index: pointer to packet indexes (modified)
- * sz: size of each packet
- */
-int
-fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz)
-{
- gf *m_dec ;
- gf **new_pkt ;
- int row, col , k = code->k ;
-
- if (GF_BITS > 8)
- sz /= 2 ;
-
- if (shuffle(pkt, index, k)) /* error if true */
- return 1 ;
- m_dec = build_decode_matrix(code, pkt, index);
-
- if (m_dec == NULL)
- return 1 ; /* error */
- /*
- * do the actual decoding
- */
- new_pkt = (gf**)my_malloc (k * sizeof (gf * ), "new pkt pointers" );
- for (row = 0 ; row < k ; row++ ) {
- if (index[row] >= k) {
- new_pkt[row] = (gf*) my_malloc (sz * sizeof (gf), "new pkt buffer" );
- bzero(new_pkt[row], sz * sizeof(gf) ) ;
- for (col = 0 ; col < k ; col++ )
- addmul(new_pkt[row], pkt[col], m_dec[row*k + col], sz) ;
- }
- }
- /*
- * move pkts to their final destination
- */
- for (row = 0 ; row < k ; row++ ) {
- if (index[row] >= k) {
- bcopy(new_pkt[row], pkt[row], sz*sizeof(gf));
- free(new_pkt[row]);
- }
- }
- free(new_pkt);
- free(m_dec);
-
- return 0;
-}
diff --git a/libtransport/src/core/forwarder_interface.h b/libtransport/src/core/forwarder_interface.h
deleted file mode 100644
index a94414d38..000000000
--- a/libtransport/src/core/forwarder_interface.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <core/udp_socket_connector.h>
-#include <hicn/transport/core/prefix.h>
-#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/utils/chrono_typedefs.h>
-
-#include <deque>
-
-namespace transport {
-
-namespace core {
-
-typedef struct {
- uint64_t rx_packets;
- uint64_t tx_packets;
- uint64_t rx_bytes;
- uint64_t tx_bytes;
- uint64_t rx_errors;
- uint64_t tx_errors;
-} Counters;
-
-template <typename Implementation, typename ConnectorType>
-class ForwarderInterface {
- static_assert(std::is_base_of<Connector, ConnectorType>::value,
- "T must inherit from connector!");
-
- static constexpr uint32_t standard_cs_reserved = 5000;
-
- protected:
- ForwarderInterface(ConnectorType &c)
- : connector_(c),
- inet_address_({}),
- inet6_address_({}),
- mtu_(1500),
- output_interface_(""),
- content_store_reserved_(standard_cs_reserved) {
- inet_address_.v4.as_u32 = htonl(0x7f00001);
- inet6_address_.v6.as_u8[15] = 0x01;
- }
-
- public:
- virtual ~ForwarderInterface() {}
-
- TRANSPORT_ALWAYS_INLINE void connect(bool is_consumer = true) {
- static_cast<Implementation &>(*this).connect(is_consumer);
- }
-
- TRANSPORT_ALWAYS_INLINE void registerRoute(Prefix &prefix) {
- static_cast<Implementation &>(*this).registerRoute();
- }
-
- TRANSPORT_ALWAYS_INLINE std::uint32_t getMtu() {
- return static_cast<Implementation &>(*this).getMtu();
- }
-
- TRANSPORT_ALWAYS_INLINE static bool isControlMessage(const uint8_t *message) {
- return Implementation::isControlMessageImpl(message);
- }
-
- template <typename R>
- TRANSPORT_ALWAYS_INLINE void processControlMessageReply(R &&packet_buffer) {
- return static_cast<Implementation &>(*this).processControlMessageReplyImpl(
- std::forward<R &&>(packet_buffer));
- }
-
- TRANSPORT_ALWAYS_INLINE void closeConnection() {
- return static_cast<Implementation &>(*this).closeConnection();
- }
-
- template <
- typename R,
- typename = std::enable_if_t<
- std::is_base_of<Packet, typename std::remove_reference_t<R>>::value,
- R>>
- TRANSPORT_ALWAYS_INLINE void send(R &&packet) {
- counters_.tx_packets++;
- counters_.tx_bytes += packet.payloadSize() + packet.headerSize();
-
- if (_is_ipv4(packet.getFormat())) {
- packet.setLocator(inet_address_);
- } else {
- packet.setLocator(inet6_address_);
- }
-
-#ifndef __vpp__
- /* In the case of VPP we try to offload checksum computation to hardware */
- packet.setChecksum();
-#endif
- connector_.send(packet.acquireMemBufReference());
- }
-
- TRANSPORT_ALWAYS_INLINE void send(const uint8_t *packet, std::size_t len) {
- counters_.tx_packets++;
- counters_.tx_bytes += len;
-
- // Perfect forwarding
- connector_.send(packet, len);
- }
-
- TRANSPORT_ALWAYS_INLINE void shutdown() { connector_.close(); }
-
- TRANSPORT_ALWAYS_INLINE Connector &getConnector() { return connector_; }
-
- TRANSPORT_ALWAYS_INLINE void setContentStoreSize(uint32_t cs_size) {
- content_store_reserved_ = cs_size;
- }
-
- TRANSPORT_ALWAYS_INLINE uint32_t getContentStoreSize() const {
- return content_store_reserved_;
- }
-
- TRANSPORT_ALWAYS_INLINE void setOutputInterface(
- const std::string &interface) {
- output_interface_ = interface;
- }
-
- TRANSPORT_ALWAYS_INLINE std::string &getOutputInterface() {
- return output_interface_;
- }
-
- protected:
- ConnectorType &connector_;
- ip_address_t inet_address_;
- ip_address_t inet6_address_;
- uint16_t mtu_;
- std::string output_interface_;
- uint32_t content_store_reserved_;
- Counters counters_;
-};
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/core/global_configuration.cc b/libtransport/src/core/global_configuration.cc
index 3e37a30a4..9da37c2fa 100644
--- a/libtransport/src/core/global_configuration.cc
+++ b/libtransport/src/core/global_configuration.cc
@@ -14,8 +14,8 @@
*/
#include <core/global_configuration.h>
+#include <glog/logging.h>
#include <hicn/transport/core/connector.h>
-#include <hicn/transport/utils/log.h>
#include <libconfig.h++>
#include <map>
@@ -32,11 +32,11 @@ bool GlobalConfiguration::parseTransportConfig(const std::string& path) {
try {
cfg.readFile(path.c_str());
} catch (const FileIOException& fioex) {
- TRANSPORT_LOGE("I/O error while reading file: %s", fioex.what());
+ LOG(ERROR) << "I/O error while reading file.";
return false;
} catch (const ParseException& pex) {
- TRANSPORT_LOGE("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(),
- pex.getError());
+ LOG(ERROR) << "Parse error at " << pex.getFile() << ":" << pex.getLine()
+ << " - " << pex.getError();
return false;
}
@@ -50,11 +50,11 @@ bool GlobalConfiguration::parseTransportConfig(const std::string& path) {
for (auto section = root.begin(); section != root.end(); section++) {
std::string name = section->getName();
std::error_code ec;
- TRANSPORT_LOGD("Parsing Section: %s", name.c_str());
+ VLOG(2) << "Parsing Section: " << name;
auto it = configuration_parsers_.find(name);
if (it != configuration_parsers_.end() && !it->second.first) {
- TRANSPORT_LOGD("Found valid configuration parser");
+ VLOG(2) << "Found valid configuration parser";
it->second.second(*section, ec);
it->second.first = true;
}
@@ -64,18 +64,17 @@ bool GlobalConfiguration::parseTransportConfig(const std::string& path) {
}
void GlobalConfiguration::parseConfiguration(const std::string& path) {
- // Check if an environment variable with the configuration path exists. COnf
+ // Check if an environment variable with the configuration path exists. Conf
// variable comes first.
std::unique_lock<std::mutex> lck(cp_mtx_);
-
if (const char* env_c = std::getenv(GlobalConfiguration::conf_file)) {
parseTransportConfig(env_c);
} else if (!path.empty()) {
conf_file_path_ = path;
parseTransportConfig(conf_file_path_);
} else {
- TRANSPORT_LOGD(
- "Called parseConfiguration but no configuration file was provided.");
+ LOG(ERROR)
+ << "Called parseConfiguration but no configuration file was provided.";
}
}
@@ -83,10 +82,9 @@ void GlobalConfiguration::registerConfigurationSetter(
const std::string& key, const SetCallback& set_callback) {
std::unique_lock<std::mutex> lck(cp_mtx_);
if (configuration_setters_.find(key) != configuration_setters_.end()) {
- TRANSPORT_LOGW(
- "Trying to register configuration setter %s twice. Ignoring second "
- "registration attempt.",
- key.c_str());
+ LOG(WARNING) << "Trying to register configuration setter " << key
+ << " twice. Ignoring second "
+ "registration attempt.";
} else {
configuration_setters_.emplace(key, set_callback);
}
@@ -96,10 +94,9 @@ void GlobalConfiguration::registerConfigurationGetter(
const std::string& key, const GetCallback& get_callback) {
std::unique_lock<std::mutex> lck(cp_mtx_);
if (configuration_getters_.find(key) != configuration_getters_.end()) {
- TRANSPORT_LOGW(
- "Trying to register configuration getter %s twice. Ignoring second "
- "registration attempt.",
- key.c_str());
+ LOG(WARNING) << "Trying to register configuration setter " << key
+ << " twice. Ignoring second "
+ "registration attempt.";
} else {
configuration_getters_.emplace(key, get_callback);
}
@@ -109,10 +106,9 @@ void GlobalConfiguration::registerConfigurationParser(
const std::string& key, const ParserCallback& parser) {
std::unique_lock<std::mutex> lck(cp_mtx_);
if (configuration_parsers_.find(key) != configuration_parsers_.end()) {
- TRANSPORT_LOGW(
- "Trying to register configuration key %s twice. Ignoring second "
- "registration attempt.",
- key.c_str());
+ LOG(WARNING) << "Trying to register configuration setter " << key
+ << " twice. Ignoring second "
+ "registration attempt.";
} else {
configuration_parsers_.emplace(key, std::make_pair(false, parser));
diff --git a/libtransport/src/core/hicn_forwarder_interface.cc b/libtransport/src/core/hicn_forwarder_interface.cc
deleted file mode 100644
index 5a0faa360..000000000
--- a/libtransport/src/core/hicn_forwarder_interface.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <core/hicn_forwarder_interface.h>
-
-union AddressLight {
- uint32_t ipv4;
- struct in6_addr ipv6;
-};
-
-typedef struct {
- uint8_t message_type;
- uint8_t command_id;
- uint16_t length;
- uint32_t seq_num;
-} CommandHeader;
-
-typedef struct {
- uint8_t message_type;
- uint8_t command_id;
- uint16_t length;
- uint32_t seq_num;
- char symbolic_or_connid[16];
- union AddressLight address;
- uint16_t cost;
- uint8_t address_type;
- uint8_t len;
-} RouteToSelfCommand;
-
-typedef struct {
- uint8_t message_type;
- uint8_t command_id;
- uint16_t length;
- uint32_t seq_num;
- char symbolic_or_connid[16];
-} DeleteSelfConnectionCommand;
-
-namespace {
-static constexpr uint8_t addr_inet = 1;
-static constexpr uint8_t addr_inet6 = 2;
-static constexpr uint8_t add_route_command = 3;
-static constexpr uint8_t delete_connection_command = 5;
-static constexpr uint8_t request_light = 0xc0;
-static constexpr char identifier[] = "SELF";
-
-void fillCommandHeader(CommandHeader *header) {
- // Allocate and fill the header
- header->message_type = request_light;
- header->length = 1;
-}
-
-RouteToSelfCommand createCommandRoute(std::unique_ptr<sockaddr> &&addr,
- uint8_t prefix_length) {
- RouteToSelfCommand command = {0};
-
- // check and set IP address
- if (addr->sa_family == AF_INET) {
- command.address_type = addr_inet;
- command.address.ipv4 = ((sockaddr_in *)addr.get())->sin_addr.s_addr;
- } else if (addr->sa_family == AF_INET6) {
- command.address_type = addr_inet6;
- command.address.ipv6 = ((sockaddr_in6 *)addr.get())->sin6_addr;
- }
-
- // Fill remaining payload fields
-#ifndef _WIN32
- strcpy(command.symbolic_or_connid, identifier);
-#else
- strcpy_s(command.symbolic_or_connid, 16, identifier);
-#endif
- command.cost = 1;
- command.len = (uint8_t)prefix_length;
-
- // Allocate and fill the header
- command.command_id = add_route_command;
- fillCommandHeader((CommandHeader *)&command);
-
- return command;
-}
-
-DeleteSelfConnectionCommand createCommandDeleteConnection() {
- DeleteSelfConnectionCommand command = {0};
- fillCommandHeader((CommandHeader *)&command);
- command.command_id = delete_connection_command;
-
-#ifndef _WIN32
- strcpy(command.symbolic_or_connid, identifier);
-#else
- strcpy_s(command.symbolic_or_connid, 16, identifier);
-#endif
-
- return command;
-}
-
-} // namespace
-
-namespace transport {
-
-namespace core {
-
-HicnForwarderInterface::HicnForwarderInterface(UdpSocketConnector &connector)
- : ForwarderInterface<HicnForwarderInterface, UdpSocketConnector>(
- connector) {}
-
-HicnForwarderInterface::~HicnForwarderInterface() {}
-
-void HicnForwarderInterface::connect(bool is_consumer) { connector_.connect(); }
-
-void HicnForwarderInterface::registerRoute(Prefix &prefix) {
- auto command = createCommandRoute(prefix.toSockaddr(),
- (uint8_t)prefix.getPrefixLength());
- send((uint8_t *)&command, sizeof(RouteToSelfCommand));
-}
-
-void HicnForwarderInterface::closeConnection() {
- auto command = createCommandDeleteConnection();
- send((uint8_t *)&command, sizeof(DeleteSelfConnectionCommand));
- connector_.close();
-}
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/core/hicn_forwarder_interface.h b/libtransport/src/core/hicn_forwarder_interface.h
deleted file mode 100644
index c4138c6c2..000000000
--- a/libtransport/src/core/hicn_forwarder_interface.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/core/prefix.h>
-
-#include <core/forwarder_interface.h>
-#include <core/udp_socket_connector.h>
-
-#include <deque>
-
-namespace transport {
-
-namespace core {
-
-class HicnForwarderInterface
- : public ForwarderInterface<HicnForwarderInterface, UdpSocketConnector> {
- static constexpr uint8_t ack_code = 0xc2;
- static constexpr uint8_t nack_code = 0xc3;
-
- public:
- union addressLight {
- uint32_t ipv4;
- struct in6_addr ipv6;
- };
-
- struct route_to_self_command {
- uint8_t messageType;
- uint8_t commandID;
- uint16_t length;
- uint32_t seqNum;
- char symbolicOrConnid[16];
- union addressLight address;
- uint16_t cost;
- uint8_t addressType;
- uint8_t len;
- };
-
- using route_to_self_command = struct route_to_self_command;
- using ConnectorType = UdpSocketConnector;
-
- HicnForwarderInterface(UdpSocketConnector &connector);
-
- ~HicnForwarderInterface();
-
- void connect(bool is_consumer);
-
- void registerRoute(Prefix &prefix);
-
- std::uint16_t getMtu() { return interface_mtu; }
-
- TRANSPORT_ALWAYS_INLINE static bool isControlMessageImpl(
- const uint8_t *message) {
- return message[0] == ack_code || message[0] == nack_code;
- }
-
- TRANSPORT_ALWAYS_INLINE void processControlMessageReplyImpl(
- Packet::MemBufPtr &&packet_buffer) {
- if (packet_buffer->data()[0] == nack_code) {
- throw errors::RuntimeException(
- "Received Nack message from hicn light forwarder.");
- }
- }
-
- void closeConnection();
-
- private:
- static constexpr std::uint16_t interface_mtu = 1500;
-};
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/core/hicn_vapi.c b/libtransport/src/core/hicn_vapi.c
deleted file mode 100644
index be556f3aa..000000000
--- a/libtransport/src/core/hicn_vapi.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/config.h>
-
-#ifdef __vpp__
-
-#include <hicn/transport/utils/log.h>
-#include <core/hicn_vapi.h>
-
-#define HICN_VPP_PLUGIN
-#include <hicn/name.h>
-#undef HICN_VPP_PLUGIN
-
-#include <vapi/vapi_safe.h>
-#include <vlib/vlib.h>
-#include <vlibapi/api.h>
-#include <vlibmemory/api.h>
-#include <vppinfra/error.h>
-
-#include <vnet/ip/format.h>
-#include <vnet/ip/ip4_packet.h>
-#include <vnet/ip/ip6_packet.h>
-#include <vapi/ip.api.vapi.h>
-
-#include <vapi/hicn.api.vapi.h>
-#include <vpp_plugins/hicn/error.h>
-
-/////////////////////////////////////////////////////
-const char *HICN_ERROR_STRING[] = {
-#define _(a, b, c) c,
- foreach_hicn_error
-#undef _
-};
-/////////////////////////////////////////////////////
-
-/*********************** Missing Symbol in vpp libraries
- * *************************/
-u8 *format_vl_api_address_union(u8 *s, va_list *args) { return NULL; }
-
-/*********************************************************************************/
-
-DEFINE_VAPI_MSG_IDS_HICN_API_JSON
-DEFINE_VAPI_MSG_IDS_IP_API_JSON
-
-static vapi_error_e register_prod_app_cb(
- vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_register_prod_app_reply *reply) {
- hicn_producer_output_params *output_params =
- (hicn_producer_output_params *)callback_ctx;
-
- if (reply == NULL) return rv;
-
- output_params->cs_reserved = reply->cs_reserved;
- output_params->prod_addr = (ip_address_t *)malloc(sizeof(ip_address_t));
- memset(output_params->prod_addr, 0, sizeof(ip_address_t));
- if (reply->prod_addr.af == ADDRESS_IP6)
- memcpy(&output_params->prod_addr->v6, reply->prod_addr.un.ip6,
- sizeof(ip6_address_t));
- else
- memcpy(&output_params->prod_addr->v4, reply->prod_addr.un.ip4,
- sizeof(ip4_address_t));
- output_params->face_id = reply->faceid;
-
- return reply->retval;
-}
-
-int hicn_vapi_register_prod_app(vapi_ctx_t ctx,
- hicn_producer_input_params *input_params,
- hicn_producer_output_params *output_params) {
- vapi_lock();
- vapi_msg_hicn_api_register_prod_app *msg =
- vapi_alloc_hicn_api_register_prod_app(ctx);
-
- if (ip46_address_is_ip4((ip46_address_t *)&input_params->prefix->address)) {
- memcpy(&msg->payload.prefix.address.un.ip4, &input_params->prefix->address,
- sizeof(ip4_address_t));
- msg->payload.prefix.address.af = ADDRESS_IP4;
- } else {
- memcpy(&msg->payload.prefix.address.un.ip6, &input_params->prefix->address,
- sizeof(ip6_address_t));
- msg->payload.prefix.address.af = ADDRESS_IP6;
- }
- msg->payload.prefix.len = input_params->prefix->len;
-
- msg->payload.swif = input_params->swif;
- msg->payload.cs_reserved = input_params->cs_reserved;
-
- int ret = vapi_hicn_api_register_prod_app(ctx, msg, register_prod_app_cb,
- output_params);
- vapi_unlock();
- return ret;
-}
-
-static vapi_error_e face_prod_del_cb(
- vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_face_prod_del_reply *reply) {
- if (reply == NULL) return rv;
-
- return reply->retval;
-}
-
-int hicn_vapi_face_prod_del(vapi_ctx_t ctx,
- hicn_del_face_app_input_params *input_params) {
- vapi_lock();
- vapi_msg_hicn_api_face_prod_del *msg = vapi_alloc_hicn_api_face_prod_del(ctx);
-
- msg->payload.faceid = input_params->face_id;
-
- int ret = vapi_hicn_api_face_prod_del(ctx, msg, face_prod_del_cb, NULL);
- vapi_unlock();
- return ret;
-}
-
-static vapi_error_e register_cons_app_cb(
- vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_register_cons_app_reply *reply) {
- hicn_consumer_output_params *output_params =
- (hicn_consumer_output_params *)callback_ctx;
-
- if (reply == NULL) return rv;
-
- output_params->src6 = (ip_address_t *)malloc(sizeof(ip_address_t));
- output_params->src4 = (ip_address_t *)malloc(sizeof(ip_address_t));
- memset(output_params->src6, 0, sizeof(ip_address_t));
- memset(output_params->src4, 0, sizeof(ip_address_t));
- memcpy(&output_params->src6->v6, &reply->src_addr6.un.ip6,
- sizeof(ip6_address_t));
- memcpy(&output_params->src4->v4, &reply->src_addr4.un.ip4,
- sizeof(ip4_address_t));
-
- output_params->face_id1 = reply->faceid1;
- output_params->face_id2 = reply->faceid2;
-
- return reply->retval;
-}
-
-int hicn_vapi_register_cons_app(vapi_ctx_t ctx,
- hicn_consumer_input_params *input_params,
- hicn_consumer_output_params *output_params) {
- vapi_lock();
- vapi_msg_hicn_api_register_cons_app *msg =
- vapi_alloc_hicn_api_register_cons_app(ctx);
-
- msg->payload.swif = input_params->swif;
-
- int ret = vapi_hicn_api_register_cons_app(ctx, msg, register_cons_app_cb,
- output_params);
- vapi_unlock();
- return ret;
-}
-
-static vapi_error_e face_cons_del_cb(
- vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_face_cons_del_reply *reply) {
- if (reply == NULL) return rv;
-
- return reply->retval;
-}
-
-int hicn_vapi_face_cons_del(vapi_ctx_t ctx,
- hicn_del_face_app_input_params *input_params) {
- vapi_lock();
- vapi_msg_hicn_api_face_cons_del *msg = vapi_alloc_hicn_api_face_cons_del(ctx);
-
- msg->payload.faceid = input_params->face_id;
-
- int ret = vapi_hicn_api_face_cons_del(ctx, msg, face_cons_del_cb, NULL);
- vapi_unlock();
- return ret;
-}
-
-static vapi_error_e reigster_route_cb(
- vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
- vapi_payload_ip_route_add_del_reply *reply) {
- if (reply == NULL) return rv;
-
- return reply->retval;
-}
-
-int hicn_vapi_register_route(vapi_ctx_t ctx,
- hicn_producer_set_route_params *input_params) {
- vapi_lock();
- vapi_msg_ip_route_add_del *msg = vapi_alloc_ip_route_add_del(ctx, 1);
-
- msg->payload.is_add = 1;
- if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
- memcpy(&msg->payload.route.prefix.address.un.ip4, &input_params->prefix->address.v4,
- sizeof(ip4_address_t));
- msg->payload.route.prefix.address.af = ADDRESS_IP4;
- msg->payload.route.prefix.len = input_params->prefix->len;
- } else {
- memcpy(&msg->payload.route.prefix.address.un.ip6, &input_params->prefix->address.v6,
- sizeof(ip6_address_t));
- msg->payload.route.prefix.address.af = ADDRESS_IP6;
- msg->payload.route.prefix.len = input_params->prefix->len;
- }
-
- msg->payload.route.paths[0].sw_if_index = ~0;
- msg->payload.route.paths[0].table_id = 0;
- if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
- memcpy(&(msg->payload.route.paths[0].nh.address.ip4), input_params->prod_addr->v4.as_u8, sizeof(ip4_address_t));
- msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
- }
- else{
- memcpy(&(msg->payload.route.paths[0].nh.address.ip6), input_params->prod_addr->v6.as_u8, sizeof(ip6_address_t));
- msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
- }
-
- msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
- msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
-
- int ret = vapi_ip_route_add_del(ctx, msg, reigster_route_cb, NULL);
-
- vapi_unlock();
- return ret;
-}
-
-char *hicn_vapi_get_error_string(int ret_val) {
- return get_error_string(ret_val);
-}
-
-#endif // __vpp__
diff --git a/libtransport/src/core/hicn_vapi.h b/libtransport/src/core/hicn_vapi.h
deleted file mode 100644
index f5d61e7ef..000000000
--- a/libtransport/src/core/hicn_vapi.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/config.h>
-#include <hicn/util/ip_address.h>
-
-#ifdef __vpp__
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <vapi/vapi.h>
-
-#include "stdint.h"
-
-typedef struct {
- ip_prefix_t* prefix;
- uint32_t swif;
- uint32_t cs_reserved;
-} hicn_producer_input_params;
-
-typedef struct {
- uint32_t swif;
-} hicn_consumer_input_params;
-
-typedef struct {
- uint32_t face_id;
-} hicn_del_face_app_input_params;
-
-typedef struct {
- uint32_t cs_reserved;
- ip_address_t* prod_addr;
- uint32_t face_id;
-} hicn_producer_output_params;
-
-typedef struct {
- ip_address_t* src4;
- ip_address_t* src6;
- uint32_t face_id1;
- uint32_t face_id2;
-} hicn_consumer_output_params;
-
-typedef struct {
- ip_prefix_t* prefix;
- ip_address_t* prod_addr;
-} hicn_producer_set_route_params;
-
-int hicn_vapi_register_prod_app(
- vapi_ctx_t ctx, hicn_producer_input_params* input_params,
- hicn_producer_output_params* output_params);
-
-int hicn_vapi_register_cons_app(
- vapi_ctx_t ctx, hicn_consumer_input_params* input_params,
- hicn_consumer_output_params* output_params);
-
-int hicn_vapi_register_route(
- vapi_ctx_t ctx, hicn_producer_set_route_params* input_params);
-
-int hicn_vapi_face_cons_del(
- vapi_ctx_t ctx, hicn_del_face_app_input_params *input_params);
-
-int hicn_vapi_face_prod_del(
- vapi_ctx_t ctx, hicn_del_face_app_input_params *input_params);
-
-char* hicn_vapi_get_error_string(int ret_val);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __vpp__
diff --git a/libtransport/src/core/interest.cc b/libtransport/src/core/interest.cc
index b4a74762d..9d868ced0 100644
--- a/libtransport/src/core/interest.cc
+++ b/libtransport/src/core/interest.cc
@@ -101,18 +101,6 @@ void Interest::setName(const Name &name) {
}
}
-void Interest::setName(Name &&name) {
- if (hicn_interest_set_name(format_, packet_start_,
- name.getStructReference()) < 0) {
- throw errors::RuntimeException("Error setting interest name.");
- }
-
- if (hicn_interest_get_name(format_, packet_start_,
- name_.getStructReference()) < 0) {
- throw errors::MalformedPacketException();
- }
-}
-
void Interest::setLocator(const ip_address_t &ip_address) {
if (hicn_interest_set_locator(format_, packet_start_, &ip_address) < 0) {
throw errors::RuntimeException("Error setting interest locator.");
@@ -175,8 +163,9 @@ void Interest::encodeSuffixes() {
// We assume interest does not hold signature for the moment.
auto int_manifest_header =
(InterestManifestHeader *)(writableData() + headerSize());
- int_manifest_header->n_suffixes = (uint32_t)suffix_set_.size();
+ int_manifest_header->n_suffixes = suffix_set_.size();
std::size_t additional_length =
+ sizeof(InterestManifestHeader) +
int_manifest_header->n_suffixes * sizeof(uint32_t);
uint32_t *suffix = (uint32_t *)(int_manifest_header + 1);
@@ -184,6 +173,7 @@ void Interest::encodeSuffixes() {
*suffix = *it;
}
+ append(additional_length);
updateLength(additional_length);
}
diff --git a/libtransport/src/core/io_module.cc b/libtransport/src/core/io_module.cc
index 7c2ec2cab..a751eabf5 100644
--- a/libtransport/src/core/io_module.cc
+++ b/libtransport/src/core/io_module.cc
@@ -16,8 +16,8 @@
#ifndef _WIN32
#include <dlfcn.h>
#endif
+#include <glog/logging.h>
#include <hicn/transport/core/io_module.h>
-#include <hicn/transport/utils/log.h>
#ifdef ANDROID
#include <io_modules/udp/hicn_forwarder_module.h>
@@ -45,16 +45,16 @@ IoModule *IoModule::load(const char *module_name) {
handle = dlopen(module_name, RTLD_NOW);
if (!handle) {
if ((error = dlerror()) != 0) {
- TRANSPORT_LOGE("%s", error);
+ LOG(ERROR) << error;
}
return 0;
}
- // link factory method
+ // get factory method
creator = (IoModule * (*)(void)) dlsym(handle, "create_module");
if (!creator) {
if ((error = dlerror()) != 0) {
- TRANSPORT_LOGE("%s", error);
+ LOG(ERROR) << error;
return 0;
}
}
diff --git a/libtransport/src/core/local_connector.cc b/libtransport/src/core/local_connector.cc
index f0e36a3d7..50dadc677 100644
--- a/libtransport/src/core/local_connector.cc
+++ b/libtransport/src/core/local_connector.cc
@@ -14,12 +14,11 @@
*/
#include <core/local_connector.h>
+#include <glog/logging.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/errors/not_implemented_exception.h>
-#include <hicn/transport/utils/log.h>
-
-#include <asio/io_service.hpp>
namespace transport {
namespace core {
@@ -33,7 +32,7 @@ void LocalConnector::send(Packet &packet) {
return;
}
- TRANSPORT_LOGD("Sending packet to local socket.");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending packet to local socket.";
io_service_.get().post([this, p{packet.shared_from_this()}]() mutable {
receive_callback_(this, *p, std::make_error_code(std::errc(0)));
});
diff --git a/libtransport/src/core/local_connector.h b/libtransport/src/core/local_connector.h
index b0daa4f53..0e2d8f676 100644
--- a/libtransport/src/core/local_connector.h
+++ b/libtransport/src/core/local_connector.h
@@ -15,17 +15,13 @@
#pragma once
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/core/global_object_pool.h>
#include <hicn/transport/utils/move_wrapper.h>
#include <hicn/transport/utils/shared_ptr_utils.h>
#include <io_modules/forwarder/errors.h>
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio/io_service.hpp>
-
namespace transport {
namespace core {
diff --git a/libtransport/src/core/manifest_format.h b/libtransport/src/core/manifest_format.h
index b759942cb..90d221f5e 100644
--- a/libtransport/src/core/manifest_format.h
+++ b/libtransport/src/core/manifest_format.h
@@ -15,7 +15,7 @@
#pragma once
-#include <hicn/transport/auth/crypto_hasher.h>
+#include <hicn/transport/auth/crypto_hash.h>
#include <hicn/transport/core/name.h>
#include <cinttypes>
diff --git a/libtransport/src/core/manifest_format_fixed.cc b/libtransport/src/core/manifest_format_fixed.cc
index 7076a4c90..11d4a56cb 100644
--- a/libtransport/src/core/manifest_format_fixed.cc
+++ b/libtransport/src/core/manifest_format_fixed.cc
@@ -34,7 +34,7 @@ FixedManifestEncoder::FixedManifestEncoder(Packet &packet,
current_entry_(0),
signature_size_(signature_size) {
if (clear) {
- memset(manifest_header_, 0, sizeof(*manifest_header_));
+ *manifest_header_ = {0};
}
}
@@ -51,7 +51,7 @@ FixedManifestEncoder &FixedManifestEncoder::clearImpl() {
packet_.trimEnd(sizeof(ManifestHeader) +
manifest_header_->number_of_entries * sizeof(ManifestEntry));
current_entry_ = 0;
- memset(manifest_header_, 0, sizeof(*manifest_header_));
+ *manifest_header_ = {0};
return *this;
}
@@ -85,8 +85,8 @@ FixedManifestEncoder &FixedManifestEncoder::setBaseNameImpl(
FixedManifestEncoder &FixedManifestEncoder::addSuffixAndHashImpl(
uint32_t suffix, const auth::CryptoHash &hash) {
- auto _hash = hash.getDigest<std::uint8_t>();
- addSuffixHashBytes(suffix, _hash.data(), _hash.length());
+ auto _hash = hash.getDigest();
+ addSuffixHashBytes(suffix, _hash.data(), _hash.size());
return *this;
}
diff --git a/libtransport/src/core/manifest_inline.h b/libtransport/src/core/manifest_inline.h
index fcb1d214f..a487ccfe3 100644
--- a/libtransport/src/core/manifest_inline.h
+++ b/libtransport/src/core/manifest_inline.h
@@ -48,7 +48,7 @@ class ManifestInline
static TRANSPORT_ALWAYS_INLINE ManifestInline *createManifest(
const core::Name &manifest_name, ManifestVersion version,
- ManifestType type, auth::CryptoHashType algorithm, bool is_last,
+ ManifestType type, HashType algorithm, bool is_last,
const Name &base_name, NextSegmentCalculationStrategy strategy,
std::size_t signature_size) {
auto manifest = new ManifestInline(manifest_name, signature_size);
@@ -110,24 +110,24 @@ class ManifestInline
// Convert several manifests into a single map from suffixes to packet hashes.
// All manifests must have been decoded beforehand.
- static std::unordered_map<Suffix, HashEntry> getSuffixMap(
+ static std::unordered_map<Suffix, Hash> getSuffixMap(
const std::vector<ManifestInline *> &manifests) {
- std::unordered_map<Suffix, HashEntry> suffix_map;
+ std::unordered_map<Suffix, Hash> suffix_map;
for (auto manifest_ptr : manifests) {
- HashType hash_algorithm = manifest_ptr->getHashAlgorithm();
+ HashType hash_type = manifest_ptr->getHashAlgorithm();
SuffixList suffix_list = manifest_ptr->getSuffixList();
for (auto it = suffix_list.begin(); it != suffix_list.end(); ++it) {
- std::vector<uint8_t> hash(
- it->second, it->second + auth::hash_size_map[hash_algorithm]);
- suffix_map[it->first] = {hash_algorithm, hash};
+ Hash hash(it->second, Hash::getSize(hash_type), hash_type);
+ suffix_map[it->first] = hash;
}
}
return suffix_map;
}
- static std::unordered_map<Suffix, HashEntry> getSuffixMap(
+
+ static std::unordered_map<Suffix, Hash> getSuffixMap(
ManifestInline *manifest) {
return getSuffixMap(std::vector<ManifestInline *>{manifest});
}
diff --git a/libtransport/src/core/memif_connector.cc b/libtransport/src/core/memif_connector.cc
deleted file mode 100644
index 087e8cba8..000000000
--- a/libtransport/src/core/memif_connector.cc
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <core/memif_connector.h>
-#include <hicn/transport/errors/not_implemented_exception.h>
-
-#ifdef __vpp__
-
-#include <sys/epoll.h>
-
-#include <cstdlib>
-
-extern "C" {
-#include <memif/libmemif.h>
-};
-
-#define CANCEL_TIMER 1
-
-namespace transport {
-
-namespace core {
-
-struct memif_connection {
- uint16_t index;
- /* memif conenction handle */
- memif_conn_handle_t conn;
- /* transmit queue id */
- uint16_t tx_qid;
- /* tx buffers */
- memif_buffer_t *tx_bufs;
- /* allocated tx buffers counter */
- /* number of tx buffers pointing to shared memory */
- uint16_t tx_buf_num;
- /* rx buffers */
- memif_buffer_t *rx_bufs;
- /* allcoated rx buffers counter */
- /* number of rx buffers pointing to shared memory */
- uint16_t rx_buf_num;
- /* interface ip address */
- uint8_t ip_addr[4];
-};
-
-std::once_flag MemifConnector::flag_;
-utils::EpollEventReactor MemifConnector::main_event_reactor_;
-
-MemifConnector::MemifConnector(PacketReceivedCallback &&receive_callback,
- OnReconnect &&on_reconnect_callback,
- asio::io_service &io_service,
- std::string app_name)
- : Connector(std::move(receive_callback), std::move(on_reconnect_callback)),
- memif_worker_(nullptr),
- timer_set_(false),
- send_timer_(std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
- disconnect_timer_(
- std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
- io_service_(io_service),
- packet_counter_(0),
- memif_connection_(std::make_unique<memif_connection_t>()),
- tx_buf_counter_(0),
- is_reconnection_(false),
- data_available_(false),
- app_name_(app_name),
- socket_filename_("") {
- std::call_once(MemifConnector::flag_, &MemifConnector::init, this);
-}
-
-MemifConnector::~MemifConnector() { close(); }
-
-void MemifConnector::init() {
- /* initialize memory interface */
- int err = memif_init(controlFdUpdate, const_cast<char *>(app_name_.c_str()),
- nullptr, nullptr, nullptr);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_init: %s", memif_strerror(err));
- }
-}
-
-void MemifConnector::connect(uint32_t memif_id, long memif_mode) {
- state_ = ConnectorState::CONNECTING;
-
- memif_id_ = memif_id;
- socket_filename_ = "/run/vpp/memif.sock";
-
- createMemif(memif_id, memif_mode, nullptr);
-
- work_ = std::make_unique<asio::io_service::work>(io_service_);
-
- while (state_ != ConnectorState::CONNECTED) {
- MemifConnector::main_event_reactor_.runOneEvent();
- }
-
- int err;
-
- /* get interrupt queue id */
- int fd = -1;
- err = memif_get_queue_efd(memif_connection_->conn, 0, &fd);
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_get_queue_efd: %s", memif_strerror(err));
- return;
- }
-
- // Remove fd from main epoll
- main_event_reactor_.delFileDescriptor(fd);
-
- // Add fd to epoll of instance
- event_reactor_.addFileDescriptor(
- fd, EPOLLIN, [this](const utils::Event &evt) -> int {
- return onInterrupt(memif_connection_->conn, this, 0);
- });
-
- memif_worker_ = std::make_unique<std::thread>(
- std::bind(&MemifConnector::threadMain, this));
-}
-
-int MemifConnector::createMemif(uint32_t index, uint8_t mode, char *s) {
- memif_connection_t *c = memif_connection_.get();
-
- /* setting memif connection arguments */
- memif_conn_args_t args;
- memset(&args, 0, sizeof(args));
-
- args.is_master = mode;
- args.log2_ring_size = MEMIF_LOG2_RING_SIZE;
- args.buffer_size = MEMIF_BUF_SIZE;
- args.num_s2m_rings = 1;
- args.num_m2s_rings = 1;
- strncpy((char *)args.interface_name, IF_NAME, strlen(IF_NAME) + 1);
- args.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP;
-
- int err;
-
- err = memif_create_socket(&args.socket, socket_filename_.c_str(), nullptr);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- throw errors::RuntimeException(memif_strerror(err));
- }
-
- args.interface_id = index;
- /* last argument for memif_create (void * private_ctx) is used by user
- to identify connection. this context is returned with callbacks */
-
- /* default interrupt */
- if (s == nullptr) {
- err = memif_create(&c->conn, &args, onConnect, onDisconnect, onInterrupt,
- this);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- throw errors::RuntimeException(memif_strerror(err));
- }
- }
-
- c->index = (uint16_t)index;
- c->tx_qid = 0;
- /* alloc memif buffers */
- c->rx_buf_num = 0;
- c->rx_bufs = static_cast<memif_buffer_t *>(
- malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
- c->tx_buf_num = 0;
- c->tx_bufs = static_cast<memif_buffer_t *>(
- malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
-
- // memif_set_rx_mode (c->conn, MEMIF_RX_MODE_POLLING, 0);
-
- return 0;
-}
-
-int MemifConnector::deleteMemif() {
- memif_connection_t *c = memif_connection_.get();
-
- if (c->rx_bufs) {
- free(c->rx_bufs);
- }
-
- c->rx_bufs = nullptr;
- c->rx_buf_num = 0;
-
- if (c->tx_bufs) {
- free(c->tx_bufs);
- }
-
- c->tx_bufs = nullptr;
- c->tx_buf_num = 0;
-
- int err;
- /* disconenct then delete memif connection */
- err = memif_delete(&c->conn);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_delete: %s", memif_strerror(err));
- }
-
- if (TRANSPORT_EXPECT_FALSE(c->conn != nullptr)) {
- TRANSPORT_LOGE("memif delete fail");
- }
-
- return 0;
-}
-
-int MemifConnector::controlFdUpdate(int fd, uint8_t events, void *private_ctx) {
- /* convert memif event definitions to epoll events */
- if (events & MEMIF_FD_EVENT_DEL) {
- return MemifConnector::main_event_reactor_.delFileDescriptor(fd);
- }
-
- uint32_t evt = 0;
-
- if (events & MEMIF_FD_EVENT_READ) {
- evt |= EPOLLIN;
- }
-
- if (events & MEMIF_FD_EVENT_WRITE) {
- evt |= EPOLLOUT;
- }
-
- if (events & MEMIF_FD_EVENT_MOD) {
- return MemifConnector::main_event_reactor_.modFileDescriptor(fd, evt);
- }
-
- return MemifConnector::main_event_reactor_.addFileDescriptor(
- fd, evt, [](const utils::Event &evt) -> int {
- uint32_t event = 0;
- int memif_err = 0;
-
- if (evt.events & EPOLLIN) {
- event |= MEMIF_FD_EVENT_READ;
- }
-
- if (evt.events & EPOLLOUT) {
- event |= MEMIF_FD_EVENT_WRITE;
- }
-
- if (evt.events & EPOLLERR) {
- event |= MEMIF_FD_EVENT_ERROR;
- }
-
- memif_err = memif_control_fd_handler(evt.data.fd, event);
-
- if (TRANSPORT_EXPECT_FALSE(memif_err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_control_fd_handler: %s",
- memif_strerror(memif_err));
- }
-
- return 0;
- });
-}
-
-int MemifConnector::bufferAlloc(long n, uint16_t qid) {
- memif_connection_t *c = memif_connection_.get();
- int err;
- uint16_t r;
- /* set data pointer to shared memory and set buffer_len to shared mmeory
- * buffer len */
- err = memif_buffer_alloc(c->conn, qid, c->tx_bufs, n, &r, 2000);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_buffer_alloc: %s", memif_strerror(err));
- return -1;
- }
-
- c->tx_buf_num += r;
- return r;
-}
-
-int MemifConnector::txBurst(uint16_t qid) {
- memif_connection_t *c = memif_connection_.get();
- int err;
- uint16_t r;
- /* inform peer memif interface about data in shared memory buffers */
- /* mark memif buffers as free */
- err = memif_tx_burst(c->conn, qid, c->tx_bufs, c->tx_buf_num, &r);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_tx_burst: %s", memif_strerror(err));
- }
-
- // err = memif_refill_queue(c->conn, qid, r, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_tx_burst: %s", memif_strerror(err));
- c->tx_buf_num -= r;
- return -1;
- }
-
- c->tx_buf_num -= r;
- return 0;
-}
-
-void MemifConnector::sendCallback(const std::error_code &ec) {
- timer_set_ = false;
-
- if (TRANSPORT_EXPECT_TRUE(!ec && state_ == ConnectorState::CONNECTED)) {
- doSend();
- }
-}
-
-void MemifConnector::processInputBuffer(std::uint16_t total_packets) {
- Packet::MemBufPtr ptr;
-
- for (; total_packets > 0; total_packets--) {
- if (input_buffer_.pop(ptr)) {
- receive_callback_(std::move(ptr));
- }
- }
-}
-
-/* informs user about connected status. private_ctx is used by user to identify
- connection (multiple connections WIP) */
-int MemifConnector::onConnect(memif_conn_handle_t conn, void *private_ctx) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
- connector->state_ = ConnectorState::CONNECTED;
- memif_refill_queue(conn, 0, -1, 0);
-
- return 0;
-}
-
-/* informs user about disconnected status. private_ctx is used by user to
- identify connection (multiple connections WIP) */
-int MemifConnector::onDisconnect(memif_conn_handle_t conn, void *private_ctx) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
- connector->state_ = ConnectorState::CLOSED;
- return 0;
-}
-
-void MemifConnector::threadMain() { event_reactor_.runEventLoop(1000); }
-
-int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
- uint16_t qid) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
-
- memif_connection_t *c = connector->memif_connection_.get();
- int err = MEMIF_ERR_SUCCESS, ret_val;
- uint16_t total_packets = 0;
- uint16_t rx;
-
- do {
- err = memif_rx_burst(conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
- ret_val = err;
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS &&
- err != MEMIF_ERR_NOBUF)) {
- TRANSPORT_LOGE("memif_rx_burst: %s", memif_strerror(err));
- goto error;
- }
-
- c->rx_buf_num += rx;
-
- if (TRANSPORT_EXPECT_FALSE(connector->io_service_.stopped())) {
- TRANSPORT_LOGE("socket stopped: ignoring %u packets", rx);
- goto error;
- }
-
- std::size_t packet_length;
- for (int i = 0; i < rx; i++) {
- auto packet = connector->getPacket();
- packet_length = (c->rx_bufs + i)->len;
- std::memcpy(packet->writableData(),
- reinterpret_cast<const uint8_t *>((c->rx_bufs + i)->data),
- packet_length);
- packet->append(packet_length);
-
- if (!connector->input_buffer_.push(std::move(packet))) {
- TRANSPORT_LOGE("Error pushing packet. Ring buffer full.");
-
- // TODO Here we should consider the possibility to signal the congestion
- // to the application, that would react properly (e.g. slow down
- // message)
- }
- }
-
- /* mark memif buffers and shared memory buffers as free */
- /* free processed buffers */
-
- err = memif_refill_queue(conn, qid, rx, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_buffer_free: %s", memif_strerror(err));
- }
-
- c->rx_buf_num -= rx;
- total_packets += rx;
-
- } while (ret_val == MEMIF_ERR_NOBUF);
-
- connector->io_service_.post(
- std::bind(&MemifConnector::processInputBuffer, connector, total_packets));
-
- return 0;
-
-error:
- err = memif_refill_queue(c->conn, qid, rx, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_buffer_free: %s", memif_strerror(err));
- }
- c->rx_buf_num -= rx;
-
- return 0;
-}
-
-void MemifConnector::close() {
- if (state_ != ConnectorState::CLOSED) {
- disconnect_timer_->expiresFromNow(std::chrono::microseconds(50));
- disconnect_timer_->asyncWait([this](const std::error_code &ec) {
- deleteMemif();
- event_reactor_.stop();
- work_.reset();
- });
-
- if (memif_worker_ && memif_worker_->joinable()) {
- memif_worker_->join();
- }
- }
-}
-
-void MemifConnector::send(const Packet::MemBufPtr &packet) {
- {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- output_buffer_.push_back(packet);
- }
-#if CANCEL_TIMER
- if (!timer_set_) {
- timer_set_ = true;
- send_timer_->expiresFromNow(std::chrono::microseconds(50));
- send_timer_->asyncWait(
- std::bind(&MemifConnector::sendCallback, this, std::placeholders::_1));
- }
-#endif
-}
-
-int MemifConnector::doSend() {
- std::size_t max = 0;
- int32_t n = 0;
- std::size_t size = 0;
-
- {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- size = output_buffer_.size();
- }
-
- do {
- max = size < MAX_MEMIF_BUFS ? size : MAX_MEMIF_BUFS;
- n = bufferAlloc(max, memif_connection_->tx_qid);
-
- if (TRANSPORT_EXPECT_FALSE(n < 0)) {
- TRANSPORT_LOGE("Error allocating buffers.");
- return -1;
- }
-
- for (uint16_t i = 0; i < n; i++) {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
-
- auto packet = output_buffer_.front().get();
- const utils::MemBuf *current = packet;
- std::size_t offset = 0;
- uint8_t *shared_buffer =
- reinterpret_cast<uint8_t *>(memif_connection_->tx_bufs[i].data);
- do {
- std::memcpy(shared_buffer + offset, current->data(), current->length());
- offset += current->length();
- current = current->next();
- } while (current != packet);
-
- memif_connection_->tx_bufs[i].len = uint32_t(offset);
-
- output_buffer_.pop_front();
- }
-
- txBurst(memif_connection_->tx_qid);
-
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- size = output_buffer_.size();
- } while (size > 0);
-
- return 0;
-}
-
-void MemifConnector::send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent) {
- throw errors::NotImplementedException();
-}
-
-} // end namespace core
-
-} // end namespace transport
-
-#endif // __vpp__
diff --git a/libtransport/src/core/memif_connector.h b/libtransport/src/core/memif_connector.h
deleted file mode 100644
index 8a0e9efad..000000000
--- a/libtransport/src/core/memif_connector.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <core/connector.h>
-#include <hicn/transport/config.h>
-#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/utils/ring_buffer.h>
-//#include <hicn/transport/core/hicn_vapi.h>
-#include <utils/epoll_event_reactor.h>
-#include <utils/fd_deadline_timer.h>
-
-#include <asio.hpp>
-#include <deque>
-#include <mutex>
-#include <thread>
-
-#ifdef __vpp__
-
-#define _Static_assert static_assert
-
-namespace transport {
-
-namespace core {
-
-typedef struct memif_connection memif_connection_t;
-
-#define APP_NAME "libtransport"
-#define IF_NAME "vpp_connection"
-
-#define MEMIF_BUF_SIZE 2048
-#define MEMIF_LOG2_RING_SIZE 13
-#define MAX_MEMIF_BUFS (1 << MEMIF_LOG2_RING_SIZE)
-
-class MemifConnector : public Connector {
- typedef void *memif_conn_handle_t;
-
- public:
- MemifConnector(PacketReceivedCallback &&receive_callback,
- OnReconnect &&on_reconnect_callback,
- asio::io_service &io_service,
- std::string app_name = "Libtransport");
-
- ~MemifConnector() override;
-
- void send(const Packet::MemBufPtr &packet) override;
-
- void send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent = 0) override;
-
- void close() override;
-
- void connect(uint32_t memif_id, long memif_mode);
-
- TRANSPORT_ALWAYS_INLINE uint32_t getMemifId() { return memif_id_; };
-
- private:
- void init();
-
- int doSend();
-
- int createMemif(uint32_t index, uint8_t mode, char *s);
-
- uint32_t getMemifConfiguration();
-
- int deleteMemif();
-
- static int controlFdUpdate(int fd, uint8_t events, void *private_ctx);
-
- static int onConnect(memif_conn_handle_t conn, void *private_ctx);
-
- static int onDisconnect(memif_conn_handle_t conn, void *private_ctx);
-
- static int onInterrupt(memif_conn_handle_t conn, void *private_ctx,
- uint16_t qid);
-
- void threadMain();
-
- int txBurst(uint16_t qid);
-
- int bufferAlloc(long n, uint16_t qid);
-
- void sendCallback(const std::error_code &ec);
-
- void processInputBuffer(std::uint16_t total_packets);
-
- private:
- static utils::EpollEventReactor main_event_reactor_;
- static std::unique_ptr<std::thread> main_worker_;
-
- int epfd;
- std::unique_ptr<std::thread> memif_worker_;
- utils::EpollEventReactor event_reactor_;
- std::atomic_bool timer_set_;
- std::unique_ptr<utils::FdDeadlineTimer> send_timer_;
- std::unique_ptr<utils::FdDeadlineTimer> disconnect_timer_;
- asio::io_service &io_service_;
- std::unique_ptr<asio::io_service::work> work_;
- uint32_t packet_counter_;
- std::unique_ptr<memif_connection_t> memif_connection_;
- uint16_t tx_buf_counter_;
-
- PacketRing input_buffer_;
- bool is_reconnection_;
- bool data_available_;
- uint32_t memif_id_;
- uint8_t memif_mode_;
- std::string app_name_;
- uint16_t transmission_index_;
- utils::SpinLock write_msgs_lock_;
- std::string socket_filename_;
-
- static std::once_flag flag_;
-};
-
-} // end namespace core
-
-} // end namespace transport
-
-#endif // __vpp__ \ No newline at end of file
diff --git a/libtransport/src/core/memif_vapi.c b/libtransport/src/core/memif_vapi.c
deleted file mode 100644
index ea3513306..000000000
--- a/libtransport/src/core/memif_vapi.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <hicn/transport/config.h>
-
-#ifdef __vpp__
-
-#include <core/memif_vapi.h>
-
-#include <fcntl.h>
-#include <inttypes.h>
-#include <semaphore.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <vapi/vapi_safe.h>
-#include <vppinfra/clib.h>
-
-DEFINE_VAPI_MSG_IDS_MEMIF_API_JSON
-
-static vapi_error_e memif_details_cb(vapi_ctx_t ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_memif_details *reply) {
- uint32_t *last_memif_id = (uint32_t *)callback_ctx;
- uint32_t current_memif_id = 0;
- if (reply != NULL) {
- current_memif_id = reply->id;
- } else {
- return rv;
- }
-
- if (current_memif_id >= *last_memif_id) {
- *last_memif_id = current_memif_id + 1;
- }
-
- return rv;
-}
-
-int memif_vapi_get_next_memif_id(vapi_ctx_t ctx, uint32_t *memif_id) {
- vapi_lock();
- vapi_msg_memif_dump *msg = vapi_alloc_memif_dump(ctx);
- int ret = vapi_memif_dump(ctx, msg, memif_details_cb, memif_id);
- vapi_unlock();
- return ret;
-}
-
-static vapi_error_e memif_create_cb(vapi_ctx_t ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_memif_create_reply *reply) {
- memif_output_params_t *output_params = (memif_output_params_t *)callback_ctx;
-
- if (reply == NULL) return rv;
-
- output_params->sw_if_index = reply->sw_if_index;
-
- return rv;
-}
-
-int memif_vapi_create_memif(vapi_ctx_t ctx, memif_create_params_t *input_params,
- memif_output_params_t *output_params) {
- vapi_lock();
- vapi_msg_memif_create *msg = vapi_alloc_memif_create(ctx);
-
- int ret = 0;
- if (input_params->socket_id == ~0) {
- // invalid socket-id
- ret = -1;
- goto END;
- }
-
- if (!is_pow2(input_params->ring_size)) {
- // ring size must be power of 2
- ret = -1;
- goto END;
- }
-
- if (input_params->rx_queues > 255 || input_params->rx_queues < 1) {
- // rx queue must be between 1 - 255
- ret = -1;
- goto END;
- }
-
- if (input_params->tx_queues > 255 || input_params->tx_queues < 1) {
- // tx queue must be between 1 - 255
- ret = -1;
- goto END;
- }
-
- msg->payload.role = input_params->role;
- msg->payload.mode = input_params->mode;
- msg->payload.rx_queues = input_params->rx_queues;
- msg->payload.tx_queues = input_params->tx_queues;
- msg->payload.id = input_params->id;
- msg->payload.socket_id = input_params->socket_id;
- msg->payload.ring_size = input_params->ring_size;
- msg->payload.buffer_size = input_params->buffer_size;
-
- ret = vapi_memif_create(ctx, msg, memif_create_cb, output_params);
-END:
- vapi_unlock();
- return ret;
-}
-
-static vapi_error_e memif_delete_cb(vapi_ctx_t ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_memif_delete_reply *reply) {
- if (reply == NULL) return rv;
-
- return reply->retval;
-}
-
-int memif_vapi_delete_memif(vapi_ctx_t ctx, uint32_t sw_if_index) {
- vapi_lock();
- vapi_msg_memif_delete *msg = vapi_alloc_memif_delete(ctx);
-
- msg->payload.sw_if_index = sw_if_index;
-
- int ret = vapi_memif_delete(ctx, msg, memif_delete_cb, NULL);
- vapi_unlock();
- return ret;
-}
-
-#endif // __vpp__
diff --git a/libtransport/src/core/memif_vapi.h b/libtransport/src/core/memif_vapi.h
deleted file mode 100644
index c045cf093..000000000
--- a/libtransport/src/core/memif_vapi.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/config.h>
-
-#ifdef __vpp__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <vapi/memif.api.vapi.h>
-#include "stdint.h"
-
-typedef struct memif_create_params_s {
- uint8_t role;
- uint8_t mode;
- uint8_t rx_queues;
- uint8_t tx_queues;
- uint32_t id;
- uint32_t socket_id;
- uint8_t secret[24];
- uint32_t ring_size;
- uint16_t buffer_size;
- uint8_t hw_addr[6];
-} memif_create_params_t;
-
-typedef struct memif_output_params_s {
- uint32_t sw_if_index;
-} memif_output_params_t;
-
-int memif_vapi_get_next_memif_id(vapi_ctx_t ctx,
- uint32_t *memif_id);
-
-int memif_vapi_create_memif(vapi_ctx_t ctx,
- memif_create_params_t *input_params,
- memif_output_params_t *output_params);
-
-int memif_vapi_delete_memif(vapi_ctx_t ctx,
- uint32_t sw_if_index);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __vpp__ \ No newline at end of file
diff --git a/libtransport/src/core/packet.cc b/libtransport/src/core/packet.cc
index 6f237729a..51337201f 100644
--- a/libtransport/src/core/packet.cc
+++ b/libtransport/src/core/packet.cc
@@ -13,10 +13,11 @@
* limitations under the License.
*/
+#include <glog/logging.h>
+#include <hicn/transport/auth/crypto_hash.h>
#include <hicn/transport/core/packet.h>
#include <hicn/transport/errors/malformed_packet_exception.h>
#include <hicn/transport/utils/hash.h>
-#include <hicn/transport/utils/log.h>
extern "C" {
#ifndef _WIN32
@@ -250,7 +251,7 @@ Packet::Format Packet::getFormat() const {
*/
if (format_ == HF_UNSPEC && length()) {
if (hicn_packet_get_format(packet_start_, &format_) < 0) {
- TRANSPORT_LOGE("Unexpected packet format.");
+ LOG(ERROR) << "Unexpected packet format HF_UNSPEC.";
}
}
@@ -262,12 +263,12 @@ std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() {
}
void Packet::dump() const {
- TRANSPORT_LOGI("HEADER -- Length: %zu", headerSize());
- TRANSPORT_LOGI("PAYLOAD -- Length: %zu", payloadSize());
+ LOG(INFO) << "HEADER -- Length: " << headerSize();
+ LOG(INFO) << "PAYLOAD -- Length: " << payloadSize();
const utils::MemBuf *current = this;
do {
- TRANSPORT_LOGI("MemBuf Length: %zu", current->length());
+ LOG(INFO) << "MemBuf Length: " << current->length();
dump((uint8_t *)current->data(), current->length());
current = current->next();
} while (current != this);
@@ -289,6 +290,19 @@ void Packet::setSignatureSize(std::size_t size_bytes) {
}
}
+void Packet::setSignatureSizeGap(std::size_t size_bytes) {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ int ret = hicn_packet_set_signature_gap(format_, packet_start_,
+ (uint8_t)size_bytes);
+
+ if (ret < 0) {
+ throw errors::RuntimeException("Error setting signature size.");
+ }
+}
+
uint8_t *Packet::getSignature() const {
if (!authenticationHeader()) {
throw errors::RuntimeException("Packet without Authentication Header.");
@@ -392,8 +406,8 @@ auth::KeyId Packet::getKeyId() const {
}
auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const {
- auth::CryptoHasher hasher(static_cast<auth::CryptoHashType>(algorithm));
- hasher.init();
+ auth::CryptoHash hash;
+ hash.setType(algorithm);
// Copy IP+TCP/ICMP header before zeroing them
hicn_header_t header_copy;
@@ -402,15 +416,10 @@ auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const {
const_cast<Packet *>(this)->resetForHash();
- const utils::MemBuf *current = this;
- do {
- hasher.updateBytes(current->data(), current->length());
- current = current->next();
- } while (current != this);
-
+ hash.computeDigest(this);
hicn_packet_copy_header(format_, &header_copy, packet_start_, false);
- return hasher.finalize();
+ return hash;
}
bool Packet::checkIntegrity() const {
diff --git a/libtransport/src/core/pending_interest.h b/libtransport/src/core/pending_interest.h
index ca6411ddf..99a8bd327 100644
--- a/libtransport/src/core/pending_interest.h
+++ b/libtransport/src/core/pending_interest.h
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/core/name.h>
@@ -23,8 +24,6 @@
#include <hicn/transport/portability/portability.h>
#include <utils/deadline_timer.h>
-#include <asio/steady_timer.hpp>
-
namespace transport {
namespace core {
@@ -80,8 +79,8 @@ class PendingInterest {
return std::move(interest_);
}
- TRANSPORT_ALWAYS_INLINE void setInterest(Interest::Ptr &&interest) {
- interest_ = std::move(interest);
+ TRANSPORT_ALWAYS_INLINE void setInterest(Interest::Ptr &interest) {
+ interest_ = interest;
}
TRANSPORT_ALWAYS_INLINE const OnContentObjectCallback &getOnDataCallback()
diff --git a/libtransport/src/core/portal.cc b/libtransport/src/core/portal.cc
index 33335e542..c4c0cf8ba 100644
--- a/libtransport/src/core/portal.cc
+++ b/libtransport/src/core/portal.cc
@@ -72,7 +72,7 @@ std::string getIoModulePath(const std::string& name,
#elif defined(MACINTOSH)
std::string extension = ".dylib";
#elif defined(WINDOWS)
- std::string extension = ".lib";
+ std::string extension = ".lib";
#else
#error "Platform not supported.";
#endif
@@ -88,8 +88,7 @@ std::string getIoModulePath(const std::string& name,
for (auto& p : paths) {
if (p.at(0) != '/') {
- TRANSPORT_LOGW("Path %s is not an absolute path. Ignoring it.",
- p.c_str());
+ LOG(WARNING) << "Path " << p << " is not an absolute path. Ignoring it.";
continue;
}
diff --git a/libtransport/src/core/portal.h b/libtransport/src/core/portal.h
index 59254cf7b..f6a9ce85b 100644
--- a/libtransport/src/core/portal.h
+++ b/libtransport/src/core/portal.h
@@ -16,7 +16,9 @@
#pragma once
#include <core/pending_interest.h>
+#include <glog/logging.h>
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/core/io_module.h>
@@ -27,10 +29,7 @@
#include <hicn/transport/interfaces/portal.h>
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/fixed_block_allocator.h>
-#include <hicn/transport/utils/log.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <future>
#include <memory>
#include <queue>
@@ -136,7 +135,7 @@ class CustomAllocatorHandler {
}
template <typename... Args>
- void operator()(Args &&...args) {
+ void operator()(Args &&... args) {
handler_(std::forward<Args>(args)...);
}
@@ -277,7 +276,8 @@ class Portal {
if (!io_module_) {
pending_interest_hash_table_.reserve(portal_details::pit_size);
io_module_.reset(IoModule::load(io_module_path_.c_str()));
- assert(io_module_);
+
+ CHECK(io_module_);
io_module_->init(std::bind(&Portal::processIncomingMessages, this,
std::placeholders::_1, std::placeholders::_2,
@@ -298,7 +298,7 @@ class Portal {
* Compute name hash
*/
TRANSPORT_ALWAYS_INLINE uint32_t getHash(const Name &name) {
- return name.getHash32() + name.getSuffix();
+ return name.getHash32(false) + name.getSuffix();
}
/**
@@ -338,15 +338,16 @@ class Portal {
interest->encodeSuffixes();
io_module_->send(*interest);
- uint32_t initial_hash = interest->getName().getHash32();
+ uint32_t initial_hash = interest->getName().getHash32(false);
auto hash = initial_hash + interest->getName().getSuffix();
+ uint32_t seq = interest->getName().getSuffix();
uint32_t *suffix = interest->firstSuffix();
auto n_suffixes = interest->numberOfSuffixes();
uint32_t counter = 0;
// Set timers
do {
auto pending_interest = packet_pool_.getPendingInterest();
- pending_interest->setInterest(std::move(interest));
+ pending_interest->setInterest(interest);
pending_interest->setOnContentObjectCallback(
std::move(on_content_object_callback));
pending_interest->setOnTimeoutCallback(
@@ -354,8 +355,9 @@ class Portal {
pending_interest->startCountdown(
portal_details::makeCustomAllocatorHandler(
- async_callback_memory_, std::bind(&Portal::timerHandler, this,
- std::placeholders::_1, hash)));
+ async_callback_memory_,
+ std::bind(&Portal::timerHandler, this, std::placeholders::_1,
+ hash, seq)));
auto it = pending_interest_hash_table_.find(hash);
if (it != pending_interest_hash_table_.end()) {
@@ -370,6 +372,7 @@ class Portal {
if (suffix) {
hash = initial_hash + *suffix;
+ seq = *suffix;
suffix++;
}
@@ -385,7 +388,7 @@ class Portal {
* @param hash - The index of the interest in the pending interest hash table.
*/
TRANSPORT_ALWAYS_INLINE void timerHandler(const std::error_code &ec,
- uint32_t hash) {
+ uint32_t hash, uint32_t seq) {
bool is_stopped = io_service_.stopped();
if (TRANSPORT_EXPECT_FALSE(is_stopped)) {
return;
@@ -398,11 +401,13 @@ class Portal {
PendingInterest::Ptr ptr = std::move(it->second);
pending_interest_hash_table_.erase(it);
auto _int = ptr->getInterest();
+ Name &name = const_cast<Name &>(_int->getName());
+ name.setSuffix(seq);
if (ptr->getOnTimeoutCallback() != UNSET_CALLBACK) {
- ptr->on_interest_timeout_callback_(std::move(_int));
+ ptr->on_interest_timeout_callback_(_int, name);
} else if (consumer_callback_) {
- consumer_callback_->onTimeout(std::move(_int));
+ consumer_callback_->onTimeout(_int, name);
}
}
}
@@ -516,6 +521,15 @@ class Portal {
}
}
+ /**
+ * Check if the transport is connected to a forwarder or not
+ */
+ TRANSPORT_ALWAYS_INLINE bool isConnectedToFwd() {
+ std::string mod = io_module_path_.substr(0, io_module_path_.find("."));
+ if (mod == "forwarder_module") return false;
+ return true;
+ }
+
private:
/**
* Clear the pending interest hash table.
@@ -578,7 +592,7 @@ class Portal {
processInterest(static_cast<Interest &>(packet_buffer));
}
} else {
- TRANSPORT_LOGE("Received not supported packet. Ignoring it.");
+ LOG(ERROR) << "Received not supported packet. Ignoring it.";
}
}
@@ -597,6 +611,7 @@ class Portal {
TRANSPORT_ALWAYS_INLINE void processInterest(Interest &interest) {
// Interest for a producer
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "processInterest " << interest.getName();
if (TRANSPORT_EXPECT_TRUE(producer_callback_ != nullptr)) {
producer_callback_->onInterest(interest);
}
@@ -612,13 +627,13 @@ class Portal {
*/
TRANSPORT_ALWAYS_INLINE void processContentObject(
ContentObject &content_object) {
- TRANSPORT_LOGD("processContentObject %s",
- content_object.getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "processContentObject " << content_object.getName();
uint32_t hash = getHash(content_object.getName());
auto it = pending_interest_hash_table_.find(hash);
if (it != pending_interest_hash_table_.end()) {
- TRANSPORT_LOGD("Found pending interest.");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Found pending interest.";
PendingInterest::Ptr interest_ptr = std::move(it->second);
pending_interest_hash_table_.erase(it);
@@ -631,7 +646,8 @@ class Portal {
consumer_callback_->onContentObject(*_int, content_object);
}
} else {
- TRANSPORT_LOGD("No interest pending for received content object.");
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "No interest pending for received content object.";
}
}
diff --git a/libtransport/src/core/raw_socket_connector.cc b/libtransport/src/core/raw_socket_connector.cc
deleted file mode 100644
index 4d780959b..000000000
--- a/libtransport/src/core/raw_socket_connector.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/utils/conversions.h>
-#include <hicn/transport/utils/log.h>
-
-#include <core/raw_socket_connector.h>
-
-#include <net/if.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#define MY_DEST_MAC0 0x0a
-#define MY_DEST_MAC1 0x7b
-#define MY_DEST_MAC2 0x7c
-#define MY_DEST_MAC3 0x1c
-#define MY_DEST_MAC4 0x4a
-#define MY_DEST_MAC5 0x14
-
-namespace transport {
-
-namespace core {
-
-RawSocketConnector::RawSocketConnector(
- PacketReceivedCallback &&receive_callback,
- OnReconnect &&on_reconnect_callback, asio::io_service &io_service,
- std::string app_name)
- : Connector(std::move(receive_callback), std::move(on_reconnect_callback)),
- io_service_(io_service),
- socket_(io_service_, raw_protocol(PF_PACKET, SOCK_RAW)),
- // resolver_(io_service_),
- timer_(io_service_),
- read_msg_(packet_pool_.makePtr(nullptr)),
- data_available_(false),
- app_name_(app_name) {
- memset(&link_layer_address_, 0, sizeof(link_layer_address_));
-}
-
-RawSocketConnector::~RawSocketConnector() {}
-
-void RawSocketConnector::connect(const std::string &interface_name,
- const std::string &mac_address_str) {
- state_ = ConnectorState::CONNECTING;
- memset(&ethernet_header_, 0, sizeof(ethernet_header_));
- struct ifreq ifr;
- struct ifreq if_mac;
- uint8_t mac_address[6];
-
- utils::convertStringToMacAddress(mac_address_str, mac_address);
-
- // Get interface mac address
- int fd = static_cast<int>(socket_.native_handle());
-
- /* Get the index of the interface to send on */
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, interface_name.c_str(), interface_name.size());
-
- // if (ioctl(fd, SIOCGIFINDEX, &if_idx) < 0) {
- // perror("SIOCGIFINDEX");
- // }
-
- /* Get the MAC address of the interface to send on */
- memset(&if_mac, 0, sizeof(struct ifreq));
- strncpy(if_mac.ifr_name, interface_name.c_str(), interface_name.size());
- if (ioctl(fd, SIOCGIFHWADDR, &if_mac) < 0) {
- perror("SIOCGIFHWADDR");
- throw errors::RuntimeException("Interface does not exist");
- }
-
- /* Ethernet header */
- for (int i = 0; i < 6; i++) {
- ethernet_header_.ether_shost[i] =
- ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[i];
- ethernet_header_.ether_dhost[i] = mac_address[i];
- }
-
- /* Ethertype field */
- ethernet_header_.ether_type = htons(ETH_P_IPV6);
-
- strcpy(ifr.ifr_name, interface_name.c_str());
-
- if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr)) {
- memcpy(link_layer_address_.sll_addr, ifr.ifr_hwaddr.sa_data, 6);
- }
-
- // memset(&ifr, 0, sizeof(ifr));
- // ioctl(fd, SIOCGIFFLAGS, &ifr);
- // ifr.ifr_flags |= IFF_PROMISC;
- // ioctl(fd, SIOCSIFFLAGS, &ifr);
-
- link_layer_address_.sll_family = AF_PACKET;
- link_layer_address_.sll_protocol = htons(ETH_P_ALL);
- link_layer_address_.sll_ifindex = if_nametoindex(interface_name.c_str());
- link_layer_address_.sll_hatype = 1;
- link_layer_address_.sll_halen = 6;
-
- // startConnectionTimer();
- doConnect();
- doRecvPacket();
-}
-
-void RawSocketConnector::send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent) {
- if (packet_sent != 0) {
- socket_.async_send(
- asio::buffer(packet, len),
- [packet_sent](std::error_code ec, std::size_t /*length*/) {
- packet_sent();
- });
- } else {
- if (state_ == ConnectorState::CONNECTED) {
- socket_.send(asio::buffer(packet, len));
- }
- }
-}
-
-void RawSocketConnector::send(const Packet::MemBufPtr &packet) {
- io_service_.post([this, packet]() {
- bool write_in_progress = !output_buffer_.empty();
- output_buffer_.push_back(std::move(packet));
- if (TRANSPORT_EXPECT_TRUE(state_ == ConnectorState::CONNECTED)) {
- if (!write_in_progress) {
- doSendPacket();
- } else {
- // Tell the handle connect it has data to write
- data_available_ = true;
- }
- }
- });
-}
-
-void RawSocketConnector::close() {
- io_service_.post([this]() { socket_.close(); });
-}
-
-void RawSocketConnector::doSendPacket() {
- auto packet = output_buffer_.front().get();
- auto array = std::vector<asio::const_buffer>();
-
- const utils::MemBuf *current = packet;
- do {
- array.push_back(asio::const_buffer(current->data(), current->length()));
- current = current->next();
- } while (current != packet);
-
- socket_.async_send(
- std::move(array),
- [this /*, packet*/](std::error_code ec, std::size_t bytes_transferred) {
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- output_buffer_.pop_front();
- if (!output_buffer_.empty()) {
- doSendPacket();
- }
- } else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
- }
- });
-}
-
-void RawSocketConnector::doRecvPacket() {
- read_msg_ = getPacket();
- socket_.async_receive(
- asio::buffer(read_msg_->writableData(), packet_size),
- [this](std::error_code ec, std::size_t bytes_transferred) mutable {
- if (!ec) {
- // Ignore packets that are not for us
- uint8_t *dst_mac_address = const_cast<uint8_t *>(read_msg_->data());
- if (!std::memcmp(dst_mac_address, ethernet_header_.ether_shost,
- ETHER_ADDR_LEN)) {
- read_msg_->append(bytes_transferred);
- read_msg_->trimStart(sizeof(struct ether_header));
- receive_callback_(std::move(read_msg_));
- }
- } else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
- }
- doRecvPacket();
- });
-}
-
-void RawSocketConnector::doConnect() {
- state_ = ConnectorState::CONNECTED;
- socket_.bind(raw_endpoint(&link_layer_address_, sizeof(link_layer_address_)));
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/core/raw_socket_connector.h b/libtransport/src/core/raw_socket_connector.h
deleted file mode 100644
index 1d4e9cb39..000000000
--- a/libtransport/src/core/raw_socket_connector.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/config.h>
-#include <hicn/transport/core/name.h>
-
-#include <core/connector.h>
-
-#include <linux/if_packet.h>
-#include <net/ethernet.h>
-#include <sys/socket.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
-#include <deque>
-
-namespace transport {
-
-namespace core {
-
-using asio::generic::raw_protocol;
-using raw_endpoint = asio::generic::basic_endpoint<raw_protocol>;
-
-class RawSocketConnector : public Connector {
- public:
- RawSocketConnector(PacketReceivedCallback &&receive_callback,
- OnReconnect &&reconnect_callback,
- asio::io_service &io_service,
- std::string app_name = "Libtransport");
-
- ~RawSocketConnector() override;
-
- void send(const Packet::MemBufPtr &packet) override;
-
- void send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent = 0) override;
-
- void close() override;
-
- void connect(const std::string &interface_name,
- const std::string &mac_address_str);
-
- private:
- void doConnect();
-
- void doRecvPacket();
-
- void doSendPacket();
-
- private:
- asio::io_service &io_service_;
- raw_protocol::socket socket_;
-
- struct ether_header ethernet_header_;
-
- struct sockaddr_ll link_layer_address_;
-
- asio::steady_timer timer_;
-
- utils::ObjectPool<utils::MemBuf>::Ptr read_msg_;
-
- bool data_available_;
- std::string app_name_;
-};
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/core/raw_socket_interface.cc b/libtransport/src/core/raw_socket_interface.cc
deleted file mode 100644
index 7ee2a844d..000000000
--- a/libtransport/src/core/raw_socket_interface.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/utils/linux.h>
-
-#include <core/raw_socket_interface.h>
-
-#include <fstream>
-
-namespace transport {
-
-namespace core {
-
-static std::string config_folder_path = "/etc/transport/interface.conf.d";
-
-RawSocketInterface::RawSocketInterface(RawSocketConnector &connector)
- : ForwarderInterface<RawSocketInterface, RawSocketConnector>(connector) {}
-
-RawSocketInterface::~RawSocketInterface() {}
-
-void RawSocketInterface::connect(bool is_consumer) {
- std::string complete_filename =
- config_folder_path + std::string("/") + output_interface_;
-
- std::ifstream is(complete_filename);
- std::string interface;
-
- if (is) {
- is >> remote_mac_address_;
- }
-
- // Get interface ip address
- struct sockaddr_in6 address = {0};
- utils::retrieveInterfaceAddress(output_interface_, &address);
-
- std::memcpy(&inet6_address_.v6.as_u8, &address.sin6_addr,
- sizeof(address.sin6_addr));
- connector_.connect(output_interface_, remote_mac_address_);
-}
-
-void RawSocketInterface::registerRoute(Prefix &prefix) { return; }
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/core/raw_socket_interface.h b/libtransport/src/core/raw_socket_interface.h
deleted file mode 100644
index c06d14637..000000000
--- a/libtransport/src/core/raw_socket_interface.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/core/prefix.h>
-
-#include <core/forwarder_interface.h>
-#include <core/raw_socket_connector.h>
-
-#include <atomic>
-#include <deque>
-
-namespace transport {
-
-namespace core {
-
-class RawSocketInterface
- : public ForwarderInterface<RawSocketInterface, RawSocketConnector> {
- public:
- typedef RawSocketConnector ConnectorType;
-
- RawSocketInterface(RawSocketConnector &connector);
-
- ~RawSocketInterface();
-
- void connect(bool is_consumer);
-
- void registerRoute(Prefix &prefix);
-
- std::uint16_t getMtu() { return interface_mtu; }
-
- TRANSPORT_ALWAYS_INLINE static bool isControlMessageImpl(
- const uint8_t *message) {
- return false;
- }
-
- TRANSPORT_ALWAYS_INLINE void processControlMessageReplyImpl(
- Packet::MemBufPtr &&packet_buffer) {}
-
- TRANSPORT_ALWAYS_INLINE void closeConnection(){};
-
- private:
- static constexpr std::uint16_t interface_mtu = 1500;
- std::string remote_mac_address_;
-};
-
-} // namespace core
-
-} // namespace transport
diff --git a/libtransport/src/core/rs.cc b/libtransport/src/core/rs.cc
deleted file mode 100644
index 33270736d..000000000
--- a/libtransport/src/core/rs.cc
+++ /dev/null
@@ -1,370 +0,0 @@
-
-/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <core/fec.h>
-#include <core/rs.h>
-#include <hicn/transport/core/global_object_pool.h>
-#include <hicn/transport/utils/log.h>
-
-#include <cassert>
-
-namespace transport {
-namespace core {
-namespace fec {
-
-BlockCode::BlockCode(uint32_t k, uint32_t n, struct fec_parms *code)
- : Packets(),
- k_(k),
- n_(n),
- code_(code),
- max_buffer_size_(0),
- current_block_size_(0),
- to_decode_(false) {
- sorted_index_.reserve(n);
-}
-
-bool BlockCode::addRepairSymbol(const fec::buffer &packet, uint32_t i) {
- // Get index
- to_decode_ = true;
- TRANSPORT_LOGD("adding symbol of size %zu", packet->length());
- return addSymbol(packet, i, packet->length() - sizeof(fec_header));
-}
-
-bool BlockCode::addSourceSymbol(const fec::buffer &packet, uint32_t i) {
- return addSymbol(packet, i, packet->length());
-}
-
-bool BlockCode::addSymbol(const fec::buffer &packet, uint32_t i,
- std::size_t size) {
- if (size > max_buffer_size_) {
- max_buffer_size_ = size;
- }
-
- operator[](current_block_size_++) = std::make_pair(i, packet);
-
- if (current_block_size_ >= k_) {
- if (to_decode_) {
- decode();
- } else {
- encode();
- }
-
- clear();
- return false;
- }
-
- return true;
-}
-
-void BlockCode::encode() {
- gf **data = new gf*[k_];
- uint32_t *old_values = new uint32_t[k_];
- uint32_t base = operator[](0).first;
-
- // Set packet length in first 2 bytes
- for (uint32_t i = 0; i < k_; i++) {
- auto &packet = operator[](i).second;
-
- TRANSPORT_LOGD("Current buffer size: %zu", packet->length());
-
- auto ret = packet->ensureCapacityAndFillUnused(max_buffer_size_, 0);
- if (TRANSPORT_EXPECT_FALSE(ret == false)) {
- throw errors::RuntimeException(
- "Provided packet is not suitable to be used as FEC source packet. "
- "Aborting.");
- }
-
- // Buffers should hold 2 bytes before the starting pointer, in order to be
- // able to set the length for the encoding operation
- packet->prepend(2);
- uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
-
- old_values[i] = *length;
- *length = htons(u_short(packet->length() - LEN_SIZE_BYTES));
-
- data[i] = packet->writableData();
-
- }
-
- // Finish to fill source block with the buffers to hold the repair symbols
- for (uint32_t i = k_; i < n_; i++) {
- // For the moment we get a packet from the pool here.. later we'll need to
- // require a packet from the caller with a callback.
- auto packet = PacketManager<>::getInstance().getMemBuf();
- packet->append(max_buffer_size_ + sizeof(fec_header) + LEN_SIZE_BYTES);
- fec_header *fh = reinterpret_cast<fec_header *>(packet->writableData());
-
- fh->setSeqNumberBase(base);
- fh->setNFecSymbols(n_ - k_);
- fh->setEncodedSymbolId(i);
- fh->setSourceBlockLen(n_);
-
- packet->trimStart(sizeof(fec_header));
-
- data[i] = packet->writableData();
- operator[](i) = std::make_pair(i, std::move(packet));
- }
-
- // Generate repair symbols and put them in corresponding buffers
- TRANSPORT_LOGD("Calling encode with max_buffer_size_ = %zu",
- max_buffer_size_);
- for (uint32_t i = k_; i < n_; i++) {
- fec_encode(code_, data, data[i], i, (int)(max_buffer_size_ + LEN_SIZE_BYTES));
- }
-
- // Restore original content of buffer space used to store the length
- for (uint32_t i = 0; i < k_; i++) {
- auto &packet = operator[](i).second;
- uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
- *length = old_values[i];
- packet->trimStart(2);
- }
-
- // Re-include header in repair packets
- for (uint32_t i = k_; i < n_; i++) {
- auto &packet = operator[](i).second;
- TRANSPORT_LOGD("Produced repair symbol of size = %zu", packet->length());
- packet->prepend(sizeof(fec_header));
- }
- delete [] data;
- delete [] old_values;
-}
-
-void BlockCode::decode() {
- gf **data = new gf*[k_];
- uint32_t *index = new uint32_t[k_];
-
- for (uint32_t i = 0; i < k_; i++) {
- auto &packet = operator[](i).second;
- index[i] = operator[](i).first;
- sorted_index_[i] = index[i];
-
- if (index[i] < k_) {
- TRANSPORT_LOGD("DECODE SOURCE - index %u - Current buffer size: %zu",
- index[i], packet->length());
- // This is a source packet. We need to prepend the length and fill
- // additional space to 0
-
- // Buffers should hold 2 bytes before the starting pointer, in order to be
- // able to set the length for the encoding operation
- packet->prepend(LEN_SIZE_BYTES);
- packet->ensureCapacityAndFillUnused(max_buffer_size_, 0);
- uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
-
- *length = htons(u_short(packet->length() - LEN_SIZE_BYTES));
- } else {
- TRANSPORT_LOGD("DECODE SYMBOL - index %u - Current buffer size: %zu",
- index[i], packet->length());
- packet->trimStart(sizeof(fec_header));
- }
-
- data[i] = packet->writableData();
- delete [] data;
- delete [] index;
- }
-
- // We decode the source block
- TRANSPORT_LOGD("Calling decode with max_buffer_size_ = %zu",
- max_buffer_size_);
- fec_decode(code_, data, reinterpret_cast<int *>(index), (int)max_buffer_size_);
-
- // Find the index in the block for recovered packets
- for (uint32_t i = 0; i < k_; i++) {
- if (index[i] != i) {
- for (uint32_t j = 0; j < k_; j++)
- if (sorted_index_[j] == uint32_t(index[i])) {
- sorted_index_[j] = i;
- }
- }
- }
-
- // Reorder block by index with in-place sorting
- for (uint32_t i = 0; i < k_; i++) {
- for (uint32_t j = sorted_index_[i]; j != i; j = sorted_index_[i]) {
- std::swap(sorted_index_[j], sorted_index_[i]);
- std::swap(operator[](j), operator[](i));
- }
- }
-
- // Adjust length according to the one written in the source packet
- for (uint32_t i = 0; i < k_; i++) {
- auto &packet = operator[](i).second;
- uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
- packet->trimStart(2);
- packet->setLength(ntohs(*length));
- }
-}
-
-void BlockCode::clear() {
- current_block_size_ = 0;
- max_buffer_size_ = 0;
- sorted_index_.clear();
- to_decode_ = false;
-}
-
-void rs::MatrixDeleter::operator()(struct fec_parms *params) {
- fec_free(params);
-}
-
-rs::Codes rs::createCodes() {
- Codes ret;
-
- ret.emplace(std::make_pair(1, 3), Matrix(fec_new(1, 3), MatrixDeleter()));
- ret.emplace(std::make_pair(6, 10), Matrix(fec_new(6, 10), MatrixDeleter()));
- ret.emplace(std::make_pair(8, 32), Matrix(fec_new(8, 32), MatrixDeleter()));
- ret.emplace(std::make_pair(10, 30), Matrix(fec_new(10, 30), MatrixDeleter()));
- ret.emplace(std::make_pair(16, 24), Matrix(fec_new(16, 24), MatrixDeleter()));
- ret.emplace(std::make_pair(10, 40), Matrix(fec_new(10, 40), MatrixDeleter()));
- ret.emplace(std::make_pair(10, 60), Matrix(fec_new(10, 60), MatrixDeleter()));
- ret.emplace(std::make_pair(10, 90), Matrix(fec_new(10, 90), MatrixDeleter()));
-
- return ret;
-}
-
-rs::Codes rs::codes_ = createCodes();
-
-rs::rs(uint32_t k, uint32_t n) : k_(k), n_(n) {}
-
-void rs::setFECCallback(const PacketsReady &callback) {
- fec_callback_ = callback;
-}
-
-encoder::encoder(uint32_t k, uint32_t n)
- : rs(k, n),
- current_code_(codes_[std::make_pair(k, n)].get()),
- source_block_(k_, n_, current_code_) {}
-
-void encoder::consume(const fec::buffer &packet, uint32_t index) {
- if (!source_block_.addSourceSymbol(packet, index)) {
- std::vector<buffer> repair_packets;
- for (uint32_t i = k_; i < n_; i++) {
- repair_packets.emplace_back(std::move(source_block_[i].second));
- }
- fec_callback_(repair_packets);
- }
-}
-
-decoder::decoder(uint32_t k, uint32_t n) : rs(k, n) {}
-
-void decoder::recoverPackets(SourceBlocks::iterator &src_block_it) {
- TRANSPORT_LOGD("recoverPackets for %u", k_);
- auto &src_block = src_block_it->second;
- std::vector<buffer> source_packets(k_);
- for (uint32_t i = 0; i < src_block.getK(); i++) {
- source_packets[i] = std::move(src_block[i].second);
- }
-
- fec_callback_(source_packets);
- processed_source_blocks_.emplace(src_block_it->first);
-
- auto it = parked_packets_.find(src_block_it->first);
- if (it != parked_packets_.end()) {
- parked_packets_.erase(it);
- }
-
- src_blocks_.erase(src_block_it);
-}
-
-void decoder::consume(const fec::buffer &packet, uint32_t index) {
- // Normalize index
- auto i = index % n_;
-
- // Get base
- uint32_t base = index - i;
-
- TRANSPORT_LOGD(
- "Decoder consume called for source symbol. BASE = %u, index = %u and i = "
- "%u",
- base, index, i);
-
- // check if a source block already exist for this symbol. If it does not
- // exist, we lazily park this packet until we receive a repair symbol for the
- // same block. This is done for 2 reason:
- // 1) If we receive all the source packets of a block, we do not need to
- // recover anything.
- // 2) Sender may change n and k at any moment, so we construct the source
- // block based on the (n, k) values written in the fec header. This is
- // actually not used right now, since we use fixed value of n and k passed
- // at construction time, but it paves the ground for a more dynamic
- // protocol that may come in the future.
- auto it = src_blocks_.find(base);
- if (it != src_blocks_.end()) {
- auto ret = it->second.addSourceSymbol(packet, i);
- if (!ret) {
- recoverPackets(it);
- }
- } else {
- TRANSPORT_LOGD("Adding to parked source packets");
- auto ret = parked_packets_.emplace(
- base, std::vector<std::pair<buffer, uint32_t> >());
- ret.first->second.emplace_back(packet, i);
- }
-}
-
-void decoder::consume(const fec::buffer &packet) {
- // Repair symbol! Get index and base source block.
- fec_header *h = reinterpret_cast<fec_header *>(packet->writableData());
- auto i = h->getEncodedSymbolId();
- auto base = h->getSeqNumberBase();
- auto n = h->getSourceBlockLen();
- auto k = n - h->getNFecSymbols();
-
- TRANSPORT_LOGD(
- "Decoder consume called for repair symbol. BASE = %u, index = %u and i = "
- "%u",
- base, base + i, i);
-
- // check if a source block already exist for this symbol
- auto it = src_blocks_.find(base);
- if (it == src_blocks_.end()) {
- // Create new source block
- auto code_it = codes_.find(std::make_pair(k, n));
- if (code_it == codes_.end()) {
- TRANSPORT_LOGE("Code for k = %u and n = %u does not exist.", k_, n_);
- return;
- }
-
- auto emplace_result =
- src_blocks_.emplace(base, BlockCode(k, n, code_it->second.get()));
- it = emplace_result.first;
-
- // Check in the parked packets and insert any packet that is part of this
- // source block
-
- auto it2 = parked_packets_.find(base);
- if (it2 != parked_packets_.end()) {
- for (auto &packet_index : it2->second) {
- auto ret =
- it->second.addSourceSymbol(packet_index.first, packet_index.second);
- if (!ret) {
- recoverPackets(it);
- // Finish to delete packets in same source block that were
- // eventually not used
- return;
- }
- }
- }
- }
-
- auto ret = it->second.addRepairSymbol(packet, i);
- if (!ret) {
- recoverPackets(it);
- }
-}
-
-} // namespace fec
-} // namespace core
-} // namespace transport
diff --git a/libtransport/src/core/tcp_socket_connector.cc b/libtransport/src/core/tcp_socket_connector.cc
index fa029c6fc..a30264271 100644
--- a/libtransport/src/core/tcp_socket_connector.cc
+++ b/libtransport/src/core/tcp_socket_connector.cc
@@ -18,8 +18,8 @@
#include <hicn/transport/portability/win_portability.h>
#endif
+#include <glog/logging.h>
#include <hicn/transport/errors/errors.h>
-#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/object_pool.h>
#include <thread>
@@ -162,7 +162,7 @@ void TcpSocketConnector::doWrite() {
// The connection has been closed by the application.
return;
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << ":" << ec.message();
tryReconnect();
}
});
@@ -182,7 +182,7 @@ void TcpSocketConnector::doReadBody(std::size_t body_length) {
// The connection has been closed by the application.
return;
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
tryReconnect();
}
});
@@ -203,23 +203,23 @@ void TcpSocketConnector::doReadHeader() {
0) {
doReadBody(body_length - length);
} else {
- TRANSPORT_LOGE("Decoding error. Ignoring packet.");
+ LOG(ERROR) << "Decoding error. Ignoring packet.";
}
} else if (ec.value() ==
static_cast<int>(std::errc::operation_canceled)) {
// The connection has been closed by the application.
return;
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
tryReconnect();
}
});
}
void TcpSocketConnector::tryReconnect() {
- if (state_ == ConnectorState::CONNECTED) {
- TRANSPORT_LOGE("Connection lost. Trying to reconnect...\n");
- state_ = ConnectorState::CONNECTING;
+ if (state_ == Connector::State::CONNECTED) {
+ LOG(ERROR) << "Connection lost. Trying to reconnect...";
+ state_ = Connector::State::CONNECTING;
is_reconnection_ = true;
io_service_.post([this]() {
if (socket_.is_open()) {
@@ -250,7 +250,7 @@ void TcpSocketConnector::doConnect() {
if (is_reconnection_) {
is_reconnection_ = false;
- TRANSPORT_LOGI("Connection recovered!\n");
+ LOG(INFO) << "Connection recovered!";
on_reconnect_callback_();
}
} else {
@@ -274,7 +274,7 @@ void TcpSocketConnector::handleDeadline(const std::error_code &ec) {
if (!ec) {
io_service_.post([this]() {
socket_.close();
- TRANSPORT_LOGE("Error connecting. Is the forwarder running?\n");
+ LOG(ERROR) << "Error connecting. Is the forwarder running?";
io_service_.stop();
});
}
diff --git a/libtransport/src/core/tcp_socket_connector.h b/libtransport/src/core/tcp_socket_connector.h
index 9dbd250d1..21db8301e 100644
--- a/libtransport/src/core/tcp_socket_connector.h
+++ b/libtransport/src/core/tcp_socket_connector.h
@@ -17,11 +17,10 @@
#include <core/connector.h>
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/utils/branch_prediction.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <deque>
namespace transport {
diff --git a/libtransport/src/core/udp_socket_connector.cc b/libtransport/src/core/udp_socket_connector.cc
deleted file mode 100644
index f5ddd6270..000000000
--- a/libtransport/src/core/udp_socket_connector.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef _WIN32
-#include <hicn/transport/portability/win_portability.h>
-#endif
-
-#include <hicn/transport/errors/errors.h>
-#include <hicn/transport/utils/log.h>
-#include <hicn/transport/utils/object_pool.h>
-
-#include <core/udp_socket_connector.h>
-
-#include <thread>
-#include <vector>
-
-namespace transport {
-
-namespace core {
-
-UdpSocketConnector::UdpSocketConnector(
- PacketReceivedCallback &&receive_callback,
- OnReconnect &&on_reconnect_callback, asio::io_service &io_service,
- std::string app_name)
- : Connector(std::move(receive_callback), std::move(on_reconnect_callback)),
- io_service_(io_service),
- socket_(io_service_),
- resolver_(io_service_),
- connection_timer_(io_service_),
- read_msg_(packet_pool_.makePtr(nullptr)),
- is_reconnection_(false),
- data_available_(false),
- app_name_(app_name) {}
-
-UdpSocketConnector::~UdpSocketConnector() {}
-
-void UdpSocketConnector::connect(std::string ip_address, std::string port) {
- endpoint_iterator_ = resolver_.resolve(
- {ip_address, port, asio::ip::resolver_query_base::numeric_service});
-
- state_ = ConnectorState::CONNECTING;
- doConnect();
-}
-
-void UdpSocketConnector::send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent) {
- if (packet_sent != 0) {
- socket_.async_send(
- asio::buffer(packet, len),
- [packet_sent](std::error_code ec, std::size_t /*length*/) {
- packet_sent();
- });
- } else {
- if (state_ == ConnectorState::CONNECTED) {
- try {
- socket_.send(asio::buffer(packet, len));
- } catch (std::system_error &err) {
- TRANSPORT_LOGE(
- "Sending of disconnect message to forwarder failed. Reason: %s",
- err.what());
- }
- }
- }
-}
-
-void UdpSocketConnector::send(const Packet::MemBufPtr &packet) {
- io_service_.post([this, packet]() {
- bool write_in_progress = !output_buffer_.empty();
- output_buffer_.push_back(std::move(packet));
- if (TRANSPORT_EXPECT_TRUE(state_ == ConnectorState::CONNECTED)) {
- if (!write_in_progress) {
- doWrite();
- }
- } else {
- // Tell the handle connect it has data to write
- data_available_ = true;
- }
- });
-}
-
-void UdpSocketConnector::close() {
- if (io_service_.stopped()) {
- doClose();
- } else {
- io_service_.dispatch(std::bind(&UdpSocketConnector::doClose, this));
- }
-}
-
-void UdpSocketConnector::doClose() {
- if (state_ != ConnectorState::CLOSED) {
- state_ = ConnectorState::CLOSED;
- if (socket_.is_open()) {
- socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
- socket_.close();
- }
- }
-}
-
-void UdpSocketConnector::doWrite() {
- auto packet = output_buffer_.front().get();
- auto array = std::vector<asio::const_buffer>();
-
- const utils::MemBuf *current = packet;
- do {
- array.push_back(asio::const_buffer(current->data(), current->length()));
- current = current->next();
- } while (current != packet);
-
- socket_.async_send(std::move(array), [this](std::error_code ec,
- std::size_t length) {
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- output_buffer_.pop_front();
- if (!output_buffer_.empty()) {
- doWrite();
- }
- } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
- // The connection has been closed by the application.
- return;
- } else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
- tryReconnect();
- }
- });
-}
-
-void UdpSocketConnector::doRead() {
- read_msg_ = getPacket();
- socket_.async_receive(
- asio::buffer(read_msg_->writableData(), Connector::packet_size),
- [this](std::error_code ec, std::size_t length) {
- if (TRANSPORT_EXPECT_TRUE(!ec)) {
- read_msg_->append(length);
- receive_callback_(std::move(read_msg_));
- doRead();
- } else if (ec.value() ==
- static_cast<int>(std::errc::operation_canceled)) {
- // The connection has been closed by the application.
- return;
- } else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
- tryReconnect();
- }
- });
-}
-
-void UdpSocketConnector::tryReconnect() {
- if (state_ == ConnectorState::CONNECTED) {
- TRANSPORT_LOGE("Connection lost. Trying to reconnect...\n");
- state_ = ConnectorState::CONNECTING;
- is_reconnection_ = true;
- io_service_.post([this]() {
- if (socket_.is_open()) {
- socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
- socket_.close();
- }
-
- doConnect();
- startConnectionTimer();
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- });
- }
-}
-
-void UdpSocketConnector::doConnect() {
- asio::async_connect(
- socket_, endpoint_iterator_,
- [this](std::error_code ec, udp::resolver::iterator) {
- if (!ec) {
- connection_timer_.cancel();
- state_ = ConnectorState::CONNECTED;
- doRead();
-
- if (data_available_) {
- data_available_ = false;
- doWrite();
- }
-
- if (is_reconnection_) {
- is_reconnection_ = false;
- }
-
- on_reconnect_callback_();
- } else {
- doConnect();
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- }
- });
-}
-
-bool UdpSocketConnector::checkConnected() {
- return state_ == ConnectorState::CONNECTED;
-}
-
-void UdpSocketConnector::startConnectionTimer() {
- connection_timer_.expires_from_now(std::chrono::seconds(60));
- connection_timer_.async_wait(std::bind(&UdpSocketConnector::handleDeadline,
- this, std::placeholders::_1));
-}
-
-void UdpSocketConnector::handleDeadline(const std::error_code &ec) {
- if (!ec) {
- io_service_.post([this]() {
- socket_.close();
- TRANSPORT_LOGE("Error connecting. Is the forwarder running?\n");
- io_service_.stop();
- });
- }
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/core/udp_socket_connector.h b/libtransport/src/core/udp_socket_connector.h
deleted file mode 100644
index 5fdb6aeec..000000000
--- a/libtransport/src/core/udp_socket_connector.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/config.h>
-#include <hicn/transport/core/name.h>
-#include <hicn/transport/utils/branch_prediction.h>
-
-#include <core/connector.h>
-
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
-#include <deque>
-
-namespace transport {
-namespace core {
-
-using asio::ip::udp;
-
-class UdpSocketConnector : public Connector {
- public:
- UdpSocketConnector(PacketReceivedCallback &&receive_callback,
- OnReconnect &&reconnect_callback,
- asio::io_service &io_service,
- std::string app_name = "Libtransport");
-
- ~UdpSocketConnector() override;
-
- void send(const Packet::MemBufPtr &packet) override;
-
- void send(const uint8_t *packet, std::size_t len,
- const PacketSentCallback &packet_sent = 0) override;
-
- void close() override;
-
- void connect(std::string ip_address = "127.0.0.1", std::string port = "9695");
-
- private:
- void doConnect();
-
- void doRead();
-
- void doWrite();
-
- void doClose();
-
- bool checkConnected();
-
- private:
- void handleDeadline(const std::error_code &ec);
-
- void startConnectionTimer();
-
- void tryReconnect();
-
- asio::io_service &io_service_;
- asio::ip::udp::socket socket_;
- asio::ip::udp::resolver resolver_;
- asio::ip::udp::resolver::iterator endpoint_iterator_;
- asio::steady_timer connection_timer_;
-
- utils::ObjectPool<utils::MemBuf>::Ptr read_msg_;
-
- bool is_reconnection_;
- bool data_available_;
-
- std::string app_name_;
-};
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/core/vpp_forwarder_interface.cc b/libtransport/src/core/vpp_forwarder_interface.cc
deleted file mode 100644
index 9f7beeb37..000000000
--- a/libtransport/src/core/vpp_forwarder_interface.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/config.h>
-
-#ifdef __vpp__
-
-#include <core/hicn_vapi.h>
-#include <core/memif_vapi.h>
-#include <core/vpp_forwarder_interface.h>
-
-extern "C" {
-#include <memif/libmemif.h>
-};
-
-typedef enum { MASTER = 0, SLAVE = 1 } memif_role_t;
-
-#define MEMIF_DEFAULT_RING_SIZE 2048
-#define MEMIF_DEFAULT_RX_QUEUES 1
-#define MEMIF_DEFAULT_TX_QUEUES 1
-#define MEMIF_DEFAULT_BUFFER_SIZE 2048
-
-namespace transport {
-
-namespace core {
-
-VPPForwarderInterface::VPPForwarderInterface(MemifConnector &connector)
- : ForwarderInterface<VPPForwarderInterface, MemifConnector>(connector),
- sw_if_index_(~0),
- face_id1_(~0),
- face_id2_(~0),
- is_consumer_(false) {}
-
-VPPForwarderInterface::~VPPForwarderInterface() {}
-
-/**
- * @brief Create a memif interface in the local VPP forwarder.
- */
-uint32_t VPPForwarderInterface::getMemifConfiguration() {
- memif_create_params_t input_params = {0};
-
- int ret =
- memif_vapi_get_next_memif_id(VPPForwarderInterface::sock_, &memif_id_);
-
- if (ret < 0) {
- throw errors::RuntimeException(
- "Error getting next memif id. Could not create memif interface.");
- }
-
- input_params.id = memif_id_;
- input_params.role = memif_role_t::MASTER;
- input_params.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP;
- input_params.rx_queues = MEMIF_DEFAULT_RX_QUEUES;
- input_params.tx_queues = MEMIF_DEFAULT_TX_QUEUES;
- input_params.ring_size = MEMIF_DEFAULT_RING_SIZE;
- input_params.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
-
- memif_output_params_t output_params = {0};
-
- ret = memif_vapi_create_memif(VPPForwarderInterface::sock_, &input_params,
- &output_params);
-
- if (ret < 0) {
- throw errors::RuntimeException(
- "Error creating memif interface in the local VPP forwarder.");
- }
-
- return output_params.sw_if_index;
-}
-
-void VPPForwarderInterface::consumerConnection() {
- hicn_consumer_input_params input = {0};
- hicn_consumer_output_params output = {0};
- ip_address_t ip4_address;
- ip_address_t ip6_address;
-
- output.src4 = &ip4_address;
- output.src6 = &ip6_address;
- input.swif = sw_if_index_;
-
- int ret = hicn_vapi_register_cons_app(VPPForwarderInterface::sock_, &input,
- &output);
-
- if (ret < 0) {
- throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
- }
-
- face_id1_ = output.face_id1;
- face_id2_ = output.face_id2;
-
- std::memcpy(inet_address_.v4.as_u8, output.src4->v4.as_u8, IPV4_ADDR_LEN);
-
- std::memcpy(inet6_address_.v6.as_u8, output.src6->v6.as_u8, IPV6_ADDR_LEN);
-}
-
-void VPPForwarderInterface::producerConnection() {
- // Producer connection will be set when we set the first route.
-}
-
-void VPPForwarderInterface::connect(bool is_consumer) {
- int retry = 20;
-
- TRANSPORT_LOGI("Connecting to VPP through vapi.");
- vapi_error_e ret = vapi_connect_safe(&sock_, 0);
-
- while (ret != VAPI_OK && retry > 0) {
- TRANSPORT_LOGE("Error connecting to VPP through vapi. Retrying..");
- --retry;
- ret = vapi_connect_safe(&sock_, 0);
- }
-
- if (ret != VAPI_OK) {
- throw std::runtime_error(
- "Impossible to connect to forwarder. Is VPP running?");
- }
-
-
- TRANSPORT_LOGI("Connected to VPP through vapi.");
-
- sw_if_index_ = getMemifConfiguration();
-
- is_consumer_ = is_consumer;
- if (is_consumer_) {
- consumerConnection();
- }
-
- connector_.connect(memif_id_, 0);
-}
-
-void VPPForwarderInterface::registerRoute(Prefix &prefix) {
- ip_prefix_t &addr = prefix.toIpPrefixStruct();
-
- ip_prefix_t producer_prefix;
- ip_address_t producer_locator;
-
- if (face_id1_ == uint32_t(~0)) {
- hicn_producer_input_params input;
- std::memset(&input, 0, sizeof(input));
-
- hicn_producer_output_params output;
- std::memset(&output, 0, sizeof(output));
-
- input.prefix = &producer_prefix;
- output.prod_addr = &producer_locator;
-
- // Here we have to ask to the actual connector what is the
- // memif_id, since this function should be called after the
- // memif creation.
- input.swif = sw_if_index_;
- input.prefix->address = addr.address;
- input.prefix->family = addr.family;
- input.prefix->len = addr.len;
- input.cs_reserved = content_store_reserved_;
-
- int ret = hicn_vapi_register_prod_app(VPPForwarderInterface::sock_, &input,
- &output);
-
- if (ret < 0) {
- throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
- }
-
- inet6_address_ = *output.prod_addr;
-
- face_id1_ = output.face_id;
- } else {
- hicn_producer_set_route_params params;
- params.prefix = &producer_prefix;
- params.prefix->address = addr.address;
- params.prefix->family = addr.family;
- params.prefix->len = addr.len;
- params.prod_addr = &producer_locator;
-
- int ret = hicn_vapi_register_route(VPPForwarderInterface::sock_, &params);
-
- if (ret < 0) {
- throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
- }
- }
-}
-
-void VPPForwarderInterface::closeConnection() {
- if (VPPForwarderInterface::sock_) {
- connector_.close();
-
- if (is_consumer_) {
- hicn_del_face_app_input_params params;
- params.face_id = face_id1_;
- hicn_vapi_face_cons_del(VPPForwarderInterface::sock_, &params);
- params.face_id = face_id2_;
- hicn_vapi_face_cons_del(VPPForwarderInterface::sock_, &params);
- } else {
- hicn_del_face_app_input_params params;
- params.face_id = face_id1_;
- hicn_vapi_face_prod_del(VPPForwarderInterface::sock_, &params);
- }
-
- if (sw_if_index_ != uint32_t(~0)) {
- int ret =
- memif_vapi_delete_memif(VPPForwarderInterface::sock_, sw_if_index_);
- if (ret < 0) {
- TRANSPORT_LOGE("Error deleting memif with sw idx %u.", sw_if_index_);
- }
- }
-
- vapi_disconnect_safe();
- VPPForwarderInterface::sock_ = nullptr;
- }
-}
-
-} // namespace core
-
-} // namespace transport
-
-#endif
diff --git a/libtransport/src/core/vpp_forwarder_interface.h b/libtransport/src/core/vpp_forwarder_interface.h
deleted file mode 100644
index 31d23b40d..000000000
--- a/libtransport/src/core/vpp_forwarder_interface.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/config.h>
-
-#ifdef __vpp__
-
-#include <hicn/transport/core/prefix.h>
-
-
-#ifdef always_inline
-#undef always_inline
-#endif
-extern "C" {
-#include <vapi/vapi_safe.h>
-};
-
-#include <core/forwarder_interface.h>
-#include <core/memif_connector.h>
-
-#include <deque>
-
-namespace transport {
-
-namespace core {
-
-class VPPForwarderInterface
- : public ForwarderInterface<VPPForwarderInterface, MemifConnector> {
- static constexpr std::uint16_t interface_mtu = 1500;
-
- public:
- VPPForwarderInterface(MemifConnector &connector);
-
- typedef MemifConnector ConnectorType;
-
- ~VPPForwarderInterface();
-
- void connect(bool is_consumer);
-
- void registerRoute(Prefix &prefix);
-
- TRANSPORT_ALWAYS_INLINE std::uint16_t getMtu() { return interface_mtu; }
-
- TRANSPORT_ALWAYS_INLINE static bool isControlMessageImpl(
- const uint8_t *message) {
- return false;
- }
-
- TRANSPORT_ALWAYS_INLINE void processControlMessageReplyImpl(
- Packet::MemBufPtr &&packet_buffer) {}
-
- void closeConnection();
-
- private:
- uint32_t getMemifConfiguration();
-
- void consumerConnection();
-
- void producerConnection();
-
- uint32_t memif_id_;
- uint32_t sw_if_index_;
- // A consumer socket in vpp has two faces (ipv4 and ipv6)
- uint32_t face_id1_;
- uint32_t face_id2_;
- bool is_consumer_;
- vapi_ctx_t sock_;
-};
-
-} // namespace core
-
-} // namespace transport
-
-#endif
diff --git a/libtransport/src/http/CMakeLists.txt b/libtransport/src/http/CMakeLists.txt
index 00708822d..2407faea3 100644
--- a/libtransport/src/http/CMakeLists.txt
+++ b/libtransport/src/http/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/client_connection.cc
${CMAKE_CURRENT_SOURCE_DIR}/request.cc
diff --git a/libtransport/src/http/client_connection.cc b/libtransport/src/http/client_connection.cc
index a24a821e7..b4ab7cbc3 100644
--- a/libtransport/src/http/client_connection.cc
+++ b/libtransport/src/http/client_connection.cc
@@ -13,14 +13,12 @@
* limitations under the License.
*/
+#include <glog/logging.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/http/client_connection.h>
#include <hicn/transport/utils/hash.h>
-#include <hicn/transport/utils/log.h>
-
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#define DEFAULT_BETA 0.99
#define DEFAULT_GAMMA 0.07
@@ -77,13 +75,12 @@ class HTTPClientConnection::Implementation
success_callback_ = [this, method = std::move(method), url = std::move(url),
start = std::move(start)](std::size_t size) -> void {
auto end = std::chrono::steady_clock::now();
- TRANSPORT_LOGI(
- "%s %s [%s] duration: %llu [usec] %zu [bytes]\n",
- method_map[method].c_str(), url.c_str(), name_.str().c_str(),
- (unsigned long long)
- std::chrono::duration_cast<std::chrono::microseconds>(end - start)
- .count(),
- size);
+ LOG(INFO) << method_map[method].c_str() << " " << url.c_str() << " ["
+ << name_.str() << "] duration: "
+ << std::chrono::duration_cast<std::chrono::microseconds>(end -
+ start)
+ .count()
+ << " [usec] " << size << " [bytes]";
};
sendRequestGetReply(ipv6_first_word);
@@ -203,8 +200,8 @@ class HTTPClientConnection::Implementation
}
void readError(const std::error_code ec) noexcept override {
- TRANSPORT_LOGE("Error %s during download of %s", ec.message().c_str(),
- current_url_.c_str());
+ LOG(ERROR) << "Error " << ec.message() << " during download of "
+ << current_url_.c_str();
if (read_bytes_callback_) {
read_bytes_callback_->onError(ec);
}
diff --git a/libtransport/src/implementation/CMakeLists.txt b/libtransport/src/implementation/CMakeLists.txt
index 392c99e15..daf899d06 100644
--- a/libtransport/src/implementation/CMakeLists.txt
+++ b/libtransport/src/implementation/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/socket.h
${CMAKE_CURRENT_SOURCE_DIR}/socket_producer.h
diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.cc b/libtransport/src/implementation/p2psecure_socket_consumer.cc
index 0b5966e71..4b14da5d2 100644
--- a/libtransport/src/implementation/p2psecure_socket_consumer.cc
+++ b/libtransport/src/implementation/p2psecure_socket_consumer.cc
@@ -251,7 +251,7 @@ int P2PSecureConsumerSocket::handshake() {
network_name_ = producer_namespace_.getRandomName();
network_name_.setSuffix(0);
- TRANSPORT_LOGD("Start handshake at %s", network_name_.toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(2)) << "Start handshake at " << network_name_;
result = SSL_connect(this->ssl_);
return result;
@@ -291,7 +291,7 @@ int P2PSecureConsumerSocket::consume(const Name &name) {
if (handshake() != 1) {
throw errors::RuntimeException("Unable to perform client handshake");
} else {
- TRANSPORT_LOGD("Handshake performed!");
+ DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!";
}
initSessionSocket();
@@ -320,7 +320,7 @@ int P2PSecureConsumerSocket::asyncConsume(const Name &name) {
if (handshake() != 1) {
throw errors::RuntimeException("Unable to perform client handshake");
} else {
- TRANSPORT_LOGD("Handshake performed!");
+ DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!";
}
initSessionSocket();
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.cc b/libtransport/src/implementation/p2psecure_socket_producer.cc
index aa14f9e37..3748001fc 100644
--- a/libtransport/src/implementation/p2psecure_socket_producer.cc
+++ b/libtransport/src/implementation/p2psecure_socket_producer.cc
@@ -50,19 +50,8 @@ P2PSecureProducerSocket::P2PSecureProducerSocket(
map_producers(),
list_producers() {
/* Setup SSL context (identity and parameter to use TLS 1.3) */
- der_cert_ = parcKeyStore_GetDEREncodedCertificate(
- (identity->getSigner()->getParcKeyStore()));
- der_prk_ = parcKeyStore_GetDEREncodedPrivateKey(
- (identity->getSigner()->getParcKeyStore()));
-
- int cert_size = (int)parcBuffer_Limit(der_cert_);
- int prk_size = (int)parcBuffer_Limit(der_prk_);
- const uint8_t *cert =
- reinterpret_cast<uint8_t *>(parcBuffer_Overlay(der_cert_, cert_size));
- const uint8_t *prk =
- reinterpret_cast<uint8_t *>(parcBuffer_Overlay(der_prk_, prk_size));
- cert_509_ = d2i_X509(NULL, &cert, cert_size);
- pkey_rsa_ = d2i_AutoPrivateKey(NULL, &prk, prk_size);
+ cert_509_ = identity->getCertificate().get();
+ pkey_rsa_ = identity->getPrivateKey().get();
/* Set the callback so that when an interest is received we catch it and we
* decrypt the payload before passing it to the application. */
@@ -73,10 +62,7 @@ P2PSecureProducerSocket::P2PSecureProducerSocket(
std::placeholders::_1, std::placeholders::_2));
}
-P2PSecureProducerSocket::~P2PSecureProducerSocket() {
- if (der_cert_) parcBuffer_Release(&der_cert_);
- if (der_prk_) parcBuffer_Release(&der_prk_);
-}
+P2PSecureProducerSocket::~P2PSecureProducerSocket() {}
void P2PSecureProducerSocket::initSessionSocket(
std::unique_ptr<TLSProducerSocket> &producer) {
@@ -128,8 +114,7 @@ void P2PSecureProducerSocket::onInterestCallback(interface::ProducerSocket &p,
TLSProducerSocket *tls_producer_ptr = tls_producer.get();
map_producers.insert({interest.getName(), move(tls_producer)});
- TRANSPORT_LOGD("Start handshake at %s",
- interest.getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Start handshake at " << interest.getName();
if (!rtc_) {
tls_producer_ptr->onInterest(*tls_producer_ptr, interest);
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.h b/libtransport/src/implementation/p2psecure_socket_producer.h
index b7c3d1958..f94347258 100644
--- a/libtransport/src/implementation/p2psecure_socket_producer.h
+++ b/libtransport/src/implementation/p2psecure_socket_producer.h
@@ -103,8 +103,6 @@ class P2PSecureProducerSocket : public ProducerSocket {
std::mutex mtx_;
/* Condition variable for the wait */
std::condition_variable cv_;
- PARCBuffer *der_cert_;
- PARCBuffer *der_prk_;
X509 *cert_509_;
EVP_PKEY *pkey_rsa_;
std::unordered_map<core::Name, std::unique_ptr<TLSProducerSocket>,
diff --git a/libtransport/src/implementation/rtc_socket_producer.cc b/libtransport/src/implementation/rtc_socket_producer.cc
deleted file mode 100644
index a5b2b4a0e..000000000
--- a/libtransport/src/implementation/rtc_socket_producer.cc
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/interfaces/callbacks.h>
-
-#include <implementation/rtc_socket_producer.h>
-#include <stdlib.h>
-#include <time.h>
-
-#define NACK_HEADER_SIZE 8 // bytes
-#define TIMESTAMP_LEN 8 // bytes
-#define TCP_HEADER_SIZE 20
-#define IP6_HEADER_SIZE 40
-#define INIT_PACKET_PRODUCTION_RATE 100 // pps random value (almost 1Mbps)
-#define STATS_INTERVAL_DURATION 500 // ms
-#define INTEREST_LIFETIME_REDUCTION_FACTOR 0.8
-#define INACTIVE_TIME \
- 500 // ms without producing before the socket
- // is considered inactive
-#define MILLI_IN_A_SEC 1000 // ms in a second
-
-#define HICN_MAX_DATA_SEQ 0xefffffff
-
-// slow production rate param
-#define MIN_PRODUCTION_RATE \
- 10 // in pacekts per sec. this value is computed
- // through experiments
-#define LIFETIME_FRACTION 0.5
-
-// NACK HEADER
-// +-----------------------------------------+
-// | 4 bytes: current segment in production |
-// +-----------------------------------------+
-// | 4 bytes: production rate (bytes x sec) |
-// +-----------------------------------------+
-//
-
-// PACKET HEADER
-// +-----------------------------------------+
-// | 8 bytes: TIMESTAMP |
-// +-----------------------------------------+
-// | packet |
-// +-----------------------------------------+
-
-namespace transport {
-namespace implementation {
-
-RTCProducerSocket::RTCProducerSocket(interface::ProducerSocket *producer_socket)
- : ProducerSocket(producer_socket),
- currentSeg_(1),
- producedBytes_(0),
- producedPackets_(0),
- bytesProductionRate_(INIT_PACKET_PRODUCTION_RATE * 1400),
- packetsProductionRate_(INIT_PACKET_PRODUCTION_RATE),
- perSecondFactor_(MILLI_IN_A_SEC / STATS_INTERVAL_DURATION),
- timer_on_(false) {
- srand((unsigned int)time(NULL));
- prodLabel_ = ((rand() % 255) << 24UL);
- interests_cache_timer_ =
- std::make_unique<asio::steady_timer>(this->getIoService());
- round_timer_ = std::make_unique<asio::steady_timer>(this->getIoService());
- setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 10000U);
- scheduleRoundTimer();
-}
-
-RTCProducerSocket::~RTCProducerSocket() {}
-
-void RTCProducerSocket::registerPrefix(const Prefix &producer_namespace) {
- ProducerSocket::registerPrefix(producer_namespace);
-
- flowName_ = producer_namespace.getName();
- auto family = flowName_.getAddressFamily();
-
- switch (family) {
- case AF_INET6:
- headerSize_ = (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET6_TCP);
- break;
- case AF_INET:
- headerSize_ = (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET_TCP);
- break;
- default:
- throw errors::RuntimeException("Unknown name format.");
- }
-}
-
-void RTCProducerSocket::scheduleRoundTimer() {
- round_timer_->expires_from_now(
- std::chrono::milliseconds(STATS_INTERVAL_DURATION));
- round_timer_->async_wait([this](std::error_code ec) {
- if (ec) return;
- updateStats();
- });
-}
-
-void RTCProducerSocket::updateStats() {
- bytesProductionRate_ = producedBytes_.load() * perSecondFactor_;
- packetsProductionRate_ = producedPackets_.load() * perSecondFactor_;
- if (packetsProductionRate_.load() == 0) packetsProductionRate_ = 1;
- producedBytes_ = 0;
- producedPackets_ = 0;
- scheduleRoundTimer();
-}
-
-void RTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) {
- auto buffer_size = buffer->length();
-
- if (TRANSPORT_EXPECT_FALSE(buffer_size == 0)) {
- return;
- }
-
- if (TRANSPORT_EXPECT_FALSE((buffer_size + headerSize_ + TIMESTAMP_LEN) >
- data_packet_size_)) {
- return;
- }
-
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- producedBytes_ += (uint32_t)(buffer_size + headerSize_ + TIMESTAMP_LEN);
- producedPackets_++;
-
- Name n(flowName_);
- auto content_object =
- std::make_shared<ContentObject>(n.setSuffix(currentSeg_.load()));
- auto payload = utils::MemBuf::create(TIMESTAMP_LEN);
-
- memcpy(payload->writableData(), &now, TIMESTAMP_LEN);
- payload->append(TIMESTAMP_LEN);
- payload->prependChain(std::move(buffer));
- content_object->appendPayload(std::move(payload));
-
- content_object->setLifetime(500); // XXX this should be set by the APP
-
- content_object->setPathLabel(prodLabel_);
-
- output_buffer_.insert(std::static_pointer_cast<ContentObject>(
- content_object->shared_from_this()));
-
- if (on_content_object_in_output_buffer_) {
- on_content_object_in_output_buffer_(*getInterface(), *content_object);
- }
-
- TRANSPORT_LOGD("Send content %u (produce)",
- content_object->getName().getSuffix());
- portal_->sendContentObject(*content_object);
-
- if (on_content_object_output_) {
- on_content_object_output_(*getInterface(), *content_object);
- }
-
- uint32_t old_curr = currentSeg_.load();
- currentSeg_ = (currentSeg_.load() + 1) % HICN_MAX_DATA_SEQ;
-
- // remove interests from the interest cache if it exists
- // this generates nacks that will tell to the consumer
- // that a new data packet was produced
- utils::SpinLock::Acquire locked(interests_cache_lock_);
- if (!seqs_map_.empty()) {
- for (auto it = seqs_map_.begin(); it != seqs_map_.end(); it++) {
- if (it->first != old_curr) sendNack(it->first);
- }
- seqs_map_.clear();
- timers_map_.clear();
- }
-}
-
-void RTCProducerSocket::onInterest(Interest::Ptr &&interest) {
- uint32_t interestSeg = interest->getName().getSuffix();
- uint32_t lifetime = interest->getLifetime();
-
- if (on_interest_input_) {
- on_interest_input_(*getInterface(), *interest);
- }
-
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- if (interestSeg > HICN_MAX_DATA_SEQ) {
- sendNack(interestSeg);
- return;
- }
-
- const std::shared_ptr<ContentObject> content_object =
- output_buffer_.find(*interest);
-
- if (content_object) {
- if (on_interest_satisfied_output_buffer_) {
- on_interest_satisfied_output_buffer_(*getInterface(), *interest);
- }
-
- if (on_content_object_output_) {
- on_content_object_output_(*getInterface(), *content_object);
- }
-
- TRANSPORT_LOGD("Send content %u (onInterest)",
- content_object->getName().getSuffix());
- portal_->sendContentObject(*content_object);
- return;
- } else {
- if (on_interest_process_) {
- on_interest_process_(*getInterface(), *interest);
- }
- }
-
- // if the production rate is less than MIN_PRODUCTION_RATE we put the
- // interest in a queue, otherwise we handle it in the usual way
- if (packetsProductionRate_.load() < MIN_PRODUCTION_RATE &&
- interestSeg >= currentSeg_.load()) {
- utils::SpinLock::Acquire locked(interests_cache_lock_);
-
- uint64_t next_timer = ~0;
- if (!timers_map_.empty()) {
- next_timer = timers_map_.begin()->first;
- }
-
- uint64_t expiration = now + (lifetime * LIFETIME_FRACTION);
- // check if the seq number exists already
- auto it_seqs = seqs_map_.find(interestSeg);
- if (it_seqs != seqs_map_.end()) {
- // the seq already exists
- if (expiration < it_seqs->second) {
- // we need to update the timer becasue we got a smaller one
- // 1) remove the entry from the multimap
- // 2) update this entry
- auto range = timers_map_.equal_range(it_seqs->second);
- for (auto it_timers = range.first; it_timers != range.second;
- it_timers++) {
- if (it_timers->second == it_seqs->first) {
- timers_map_.erase(it_timers);
- break;
- }
- }
- timers_map_.insert(
- std::pair<uint64_t, uint32_t>(expiration, interestSeg));
- it_seqs->second = expiration;
- } else {
- // nothing to do here
- return;
- }
- } else {
- // add the new seq
- timers_map_.insert(
- std::pair<uint64_t, uint32_t>(expiration, interestSeg));
- seqs_map_.insert(std::pair<uint32_t, uint64_t>(interestSeg, expiration));
- }
-
- // here we have at least one interest in the queue, we need to start or
- // update the timer
- if (!timer_on_) {
- // set timeout
- timer_on_ = true;
- scheduleCacheTimer(timers_map_.begin()->first - now);
- } else {
- // re-schedule the timer because a new interest will expires sooner
- if (next_timer > timers_map_.begin()->first) {
- interests_cache_timer_->cancel();
- scheduleCacheTimer(timers_map_.begin()->first - now);
- }
- }
- return;
- }
-
- uint32_t max_gap = (uint32_t)floor(
- (double)((double)((double)lifetime * INTEREST_LIFETIME_REDUCTION_FACTOR /
- 1000.0) *
- (double)packetsProductionRate_.load()));
-
- if (interestSeg < currentSeg_.load() ||
- interestSeg > (max_gap + currentSeg_.load())) {
- sendNack(interestSeg);
- }
- // else drop packet
-}
-
-void RTCProducerSocket::scheduleCacheTimer(uint64_t wait) {
- interests_cache_timer_->expires_from_now(std::chrono::milliseconds(wait));
- interests_cache_timer_->async_wait([this](std::error_code ec) {
- if (ec) return;
- interestCacheTimer();
- });
-}
-
-void RTCProducerSocket::interestCacheTimer() {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- utils::SpinLock::Acquire locked(interests_cache_lock_);
-
- for (auto it_timers = timers_map_.begin(); it_timers != timers_map_.end();) {
- uint64_t expire = it_timers->first;
- if (expire <= now) {
- uint32_t seq = it_timers->second;
- sendNack(seq);
- // remove the interest from the other map
- seqs_map_.erase(seq);
- it_timers = timers_map_.erase(it_timers);
- } else {
- // stop, we are done!
- break;
- }
- }
- if (timers_map_.empty()) {
- timer_on_ = false;
- } else {
- timer_on_ = true;
- scheduleCacheTimer(timers_map_.begin()->first - now);
- }
-}
-
-void RTCProducerSocket::sendNack(uint32_t sequence) {
- auto nack_payload = utils::MemBuf::create(NACK_HEADER_SIZE);
- nack_payload->append(NACK_HEADER_SIZE);
- ContentObject nack;
-
- Name n(flowName_);
- nack.appendPayload(std::move(nack_payload));
- nack.setName(n.setSuffix(sequence));
-
- uint32_t *payload_ptr = (uint32_t *)nack.getPayload()->data();
- *payload_ptr = currentSeg_.load();
-
- *(++payload_ptr) = bytesProductionRate_.load();
-
- nack.setLifetime(0);
- nack.setPathLabel(prodLabel_);
-
- if (on_content_object_output_) {
- on_content_object_output_(*getInterface(), nack);
- }
-
- TRANSPORT_LOGD("Send nack %u", sequence);
- portal_->sendContentObject(nack);
-}
-
-} // namespace implementation
-
-} // end namespace transport
diff --git a/libtransport/src/implementation/rtc_socket_producer.h b/libtransport/src/implementation/rtc_socket_producer.h
deleted file mode 100644
index 87db2121d..000000000
--- a/libtransport/src/implementation/rtc_socket_producer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <implementation/socket_producer.h>
-#include <utils/content_store.h>
-
-#include <atomic>
-#include <map>
-#include <mutex>
-
-namespace transport {
-namespace implementation {
-
-class RTCProducerSocket : virtual public ProducerSocket {
- public:
- RTCProducerSocket(interface::ProducerSocket *producer_socket);
-
- ~RTCProducerSocket();
-
- void registerPrefix(const Prefix &producer_namespace) override;
- void produce(std::unique_ptr<utils::MemBuf> &&buffer) override;
-
- private:
- void onInterest(Interest::Ptr &&interest) override;
- void sendNack(uint32_t sequence);
- void updateStats();
- void scheduleCacheTimer(uint64_t wait);
- void scheduleRoundTimer();
- void interestCacheTimer();
-
- std::atomic<uint32_t> currentSeg_;
- uint32_t prodLabel_;
- uint16_t headerSize_;
- Name flowName_;
- std::atomic<uint32_t> producedBytes_;
- std::atomic<uint32_t> producedPackets_;
- std::atomic<uint32_t> bytesProductionRate_;
- std::atomic<uint32_t> packetsProductionRate_;
- uint32_t perSecondFactor_;
-
- std::unique_ptr<asio::steady_timer> round_timer_;
-
- // cache for the received interests
- // this map maps the expiration time of an interest to
- // its sequence number. the map is sorted by timeouts
- // the same timeout may be used for multiple sequence numbers
- // but for each sequence number we store only the smallest
- // expiry time. In this way the mapping from seqs_map_ to
- // timers_map_ is unique
- std::multimap<uint64_t, uint32_t> timers_map_;
- // this map does the opposite, this map is not ordered
- std::unordered_map<uint32_t, uint64_t> seqs_map_;
- bool timer_on_;
- std::unique_ptr<asio::steady_timer> interests_cache_timer_;
- utils::SpinLock interests_cache_lock_;
-};
-
-} // namespace implementation
-
-} // end namespace transport
diff --git a/libtransport/src/implementation/socket_consumer.h b/libtransport/src/implementation/socket_consumer.h
index a7b6ac4e7..e0981af7f 100644
--- a/libtransport/src/implementation/socket_consumer.h
+++ b/libtransport/src/implementation/socket_consumer.h
@@ -15,10 +15,10 @@
#pragma once
+#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/statistics.h>
-#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/utils/event_thread.h>
#include <protocols/cbr.h>
#include <protocols/raaqm.h>
@@ -777,7 +777,7 @@ class ConsumerSocket : public Socket {
// Verification parameters
std::shared_ptr<auth::Verifier> verifier_;
- PARCKeyId *key_id_;
+ transport::auth::KeyId *key_id_;
std::atomic_bool verify_signature_;
bool reset_window_;
diff --git a/libtransport/src/implementation/socket_producer.h b/libtransport/src/implementation/socket_producer.h
index f511f7743..9daf79b9d 100644
--- a/libtransport/src/implementation/socket_producer.h
+++ b/libtransport/src/implementation/socket_producer.h
@@ -51,7 +51,7 @@ class ProducerSocket : public Socket {
content_object_expiry_time_(default_values::content_object_expiry_time),
async_thread_(),
making_manifest_(false),
- hash_algorithm_(auth::CryptoHashType::SHA_256),
+ hash_algorithm_(auth::CryptoHashType::SHA256),
suffix_strategy_(core::NextSegmentCalculationStrategy::INCREMENTAL),
on_interest_input_(VOID_HANDLER),
on_interest_dropped_input_buffer_(VOID_HANDLER),
@@ -417,7 +417,7 @@ class ProducerSocket : public Socket {
uint32_t &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
- socket_option_value = (uint32_t)production_protocol_->getOutputBufferSize();
+ socket_option_value = production_protocol_->getOutputBufferSize();
break;
case GeneralTransportOptions::DATA_PACKET_SIZE:
diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.cc b/libtransport/src/implementation/tls_rtc_socket_producer.cc
index 9a62c8683..db62b10c1 100644
--- a/libtransport/src/implementation/tls_rtc_socket_producer.cc
+++ b/libtransport/src/implementation/tls_rtc_socket_producer.cc
@@ -156,7 +156,7 @@ void TLSRTCProducerSocket::accept() {
throw errors::RuntimeException("Unable to perform client handshake");
}
- TRANSPORT_LOGD("Handshake performed!");
+ DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!";
parent_->list_producers.push_front(
std::move(parent_->map_producers[handshake_name_]));
diff --git a/libtransport/src/implementation/tls_socket_producer.cc b/libtransport/src/implementation/tls_socket_producer.cc
index dd92e58cf..3992ca45c 100644
--- a/libtransport/src/implementation/tls_socket_producer.cc
+++ b/libtransport/src/implementation/tls_socket_producer.cc
@@ -48,13 +48,13 @@ int TLSProducerSocket::readOld(BIO *b, char *buf, int size) {
std::unique_lock<std::mutex> lck(socket->mtx_);
- TRANSPORT_LOGD("Start wait on the CV.");
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Start wait on the CV.";
if (!socket->something_to_read_) {
(socket->cv_).wait(lck);
}
- TRANSPORT_LOGD("CV unlocked.");
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "CV unlocked.";
/* Either there already is something to read, or the thread has been waken up.
* We must return the payload in the interest anyway */
@@ -253,7 +253,7 @@ void TLSProducerSocket::accept() {
}
handshake_state_ = SERVER_FINISHED;
- TRANSPORT_LOGD("Handshake performed!");
+ DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!";
}
int TLSProducerSocket::async_accept() {
@@ -305,7 +305,7 @@ void TLSProducerSocket::cacheMiss(interface::ProducerSocket &p,
Interest &interest) {
HandshakeState handshake_state = getHandshakeState();
- TRANSPORT_LOGD("On cache miss in TLS socket producer.");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "On cache miss in TLS socket producer.";
if (handshake_state == CLIENT_HELLO) {
std::unique_lock<std::mutex> lck(mtx_);
@@ -390,7 +390,8 @@ int TLSProducerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type,
void *add_arg) {
TLSProducerSocket *socket = reinterpret_cast<TLSProducerSocket *>(add_arg);
- TRANSPORT_LOGD("On addHicnKeyIdCb, for the prefix registration.");
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "On addHicnKeyIdCb, for the prefix registration.";
if (ext_type == 100) {
auto &prefix =
diff --git a/libtransport/src/interfaces/CMakeLists.txt b/libtransport/src/interfaces/CMakeLists.txt
index 0284aa412..7ec024fec 100644
--- a/libtransport/src/interfaces/CMakeLists.txt
+++ b/libtransport/src/interfaces/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/socket_consumer.cc
diff --git a/libtransport/src/interfaces/global_configuration.cc b/libtransport/src/interfaces/global_configuration.cc
index 8fb6601f3..cecdacc07 100644
--- a/libtransport/src/interfaces/global_configuration.cc
+++ b/libtransport/src/interfaces/global_configuration.cc
@@ -14,8 +14,8 @@
*/
#include <core/global_configuration.h>
+#include <glog/logging.h>
#include <hicn/transport/interfaces/global_conf_interface.h>
-#include <hicn/transport/utils/log.h>
#include <system_error>
@@ -32,7 +32,7 @@ void ConfigurationObject::get() {
core::GlobalConfiguration::getInstance().getConfiguration(*this, ec);
if (ec) {
- TRANSPORT_LOGE("Error setting global config: %s", ec.message().c_str());
+ LOG(ERROR) << "Error setting global config: " << ec.message();
}
}
@@ -41,7 +41,7 @@ void ConfigurationObject::set() {
core::GlobalConfiguration::getInstance().setConfiguration(*this, ec);
if (ec) {
- TRANSPORT_LOGE("Error setting global config: %s", ec.message().c_str());
+ LOG(ERROR) << "Error setting global config: " << ec.message();
}
}
diff --git a/libtransport/src/interfaces/portal.cc b/libtransport/src/interfaces/portal.cc
index 2ab51c4b9..9db0621f6 100644
--- a/libtransport/src/interfaces/portal.cc
+++ b/libtransport/src/interfaces/portal.cc
@@ -94,4 +94,4 @@ void Portal::registerRoute(core::Prefix &prefix) {
} // namespace interface
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/io_modules/CMakeLists.txt b/libtransport/src/io_modules/CMakeLists.txt
index cf466721f..29aec236a 100644
--- a/libtransport/src/io_modules/CMakeLists.txt
+++ b/libtransport/src/io_modules/CMakeLists.txt
@@ -11,10 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-if (${CMAKE_SYSTEM_NAME} MATCHES "^(iOS|Android|Windows)$")
-
+if (${CMAKE_SYSTEM_NAME} MATCHES Android)
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/udp/hicn_forwarder_module.cc
${CMAKE_CURRENT_SOURCE_DIR}/udp/udp_socket_connector.cc
@@ -27,7 +24,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "^(iOS|Android|Windows)$")
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
-else ()
+else()
add_subdirectory(udp)
add_subdirectory(loopback)
add_subdirectory(forwarder)
diff --git a/libtransport/src/io_modules/forwarder/CMakeLists.txt b/libtransport/src/io_modules/forwarder/CMakeLists.txt
index 92662bc4c..a1d0c5db5 100644
--- a/libtransport/src/io_modules/forwarder/CMakeLists.txt
+++ b/libtransport/src/io_modules/forwarder/CMakeLists.txt
@@ -11,9 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-
list(APPEND MODULE_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/connector.h
${CMAKE_CURRENT_SOURCE_DIR}/endpoint.h
@@ -37,7 +34,7 @@ build_module(forwarder_module
SHARED
SOURCES ${MODULE_SOURCE_FILES}
DEPENDS ${DEPENDENCIES}
- COMPONENT lib${LIBTRANSPORT}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}-io-modules
INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
COMPILE_OPTIONS ${COMPILE_FLAGS}
diff --git a/libtransport/src/io_modules/forwarder/forwarder.cc b/libtransport/src/io_modules/forwarder/forwarder.cc
index 7e89e2f9f..0546cb8b3 100644
--- a/libtransport/src/io_modules/forwarder/forwarder.cc
+++ b/libtransport/src/io_modules/forwarder/forwarder.cc
@@ -15,6 +15,7 @@
#include <core/global_configuration.h>
#include <core/local_connector.h>
+#include <glog/logging.h>
#include <io_modules/forwarder/forwarder.h>
#include <io_modules/forwarder/global_id_counter.h>
#include <io_modules/forwarder/udp_tunnel.h>
@@ -127,7 +128,7 @@ void Forwarder::onPacketFromListener(Connector *connector,
std::bind(&Forwarder::onPacketReceived, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3));
- TRANSPORT_LOGD("Packet received from listener.");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Packet received from listener.";
{
utils::SpinLock::Acquire locked(connector_lock_);
@@ -157,10 +158,8 @@ void Forwarder::onPacketReceived(Connector *connector,
if ((is_producer && is_interest) || (!is_producer && !is_interest)) {
c.second->send(*packet);
} else {
- TRANSPORT_LOGD(
- "Error sending packet to local connector. is_interest = %d - "
- "is_producer = %d",
- (int)is_interest, (int)is_producer);
+ LOG(ERROR) << "Error sending packet to local connector. is_interest = "
+ << is_interest << " - is_producer = " << is_producer;
}
}
@@ -178,9 +177,9 @@ void Forwarder::send(Packet &packet) {
auto remote_endpoint =
remote_connectors_.begin()->second->getRemoteEndpoint();
- TRANSPORT_LOGD("Sending packet to: %s:%u",
- remote_endpoint.getAddress().to_string().c_str(),
- remote_endpoint.getPort());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Sending packet to: " << remote_endpoint.getAddress() << ":"
+ << remote_endpoint.getPort();
remote_connectors_.begin()->second->send(packet);
}
@@ -199,7 +198,7 @@ void Forwarder::parseForwarderConfiguration(
// Get number of threads
int n_threads = 1;
forwarder_config.lookupValue("n_threads", n_threads);
- TRANSPORT_LOGD("Forwarder threads from config file: %u", n_threads);
+ VLOG(1) << "Forwarder threads from config file: " << n_threads;
config_.setThreadNumber(n_threads);
}
@@ -219,8 +218,8 @@ void Forwarder::parseForwarderConfiguration(
listener.lookupValue("local_port", port);
list.port = (uint16_t)(port);
- TRANSPORT_LOGD("Adding listener %s, (%s:%u)", list.name.c_str(),
- list.address.c_str(), list.port);
+ VLOG(1) << "Adding listener " << list.name << ", ( " << list.address
+ << ":" << list.port << ")";
config_.addListener(std::move(list));
}
}
@@ -262,9 +261,9 @@ void Forwarder::parseForwarderConfiguration(
conn.remote_port = (uint16_t)(port);
- TRANSPORT_LOGD("Adding connector %s, (%s:%u %s:%u)", conn.name.c_str(),
- conn.local_address.c_str(), conn.local_port,
- conn.remote_address.c_str(), conn.remote_port);
+ VLOG(1) << "Adding connector " << conn.name << ", (" << conn.local_address
+ << ":" << conn.local_port << " " << conn.remote_address << ":"
+ << conn.remote_port << ")";
config_.addConnector(std::move(conn));
}
}
@@ -285,8 +284,8 @@ void Forwarder::parseForwarderConfiguration(
route.lookupValue("connector", r.connector);
r.weight = (uint16_t)(weight);
- TRANSPORT_LOGD("Adding route %s %s (%s %u)", r.name.c_str(),
- r.prefix.c_str(), r.connector.c_str(), r.weight);
+ VLOG(1) << "Adding route " << r.name << " " << r.prefix << " ("
+ << r.connector << " " << r.weight << ")";
config_.addRoute(std::move(r));
}
}
diff --git a/libtransport/src/io_modules/forwarder/forwarder_module.cc b/libtransport/src/io_modules/forwarder/forwarder_module.cc
index 356b42d3b..4f95b9ca0 100644
--- a/libtransport/src/io_modules/forwarder/forwarder_module.cc
+++ b/libtransport/src/io_modules/forwarder/forwarder_module.cc
@@ -13,8 +13,8 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/errors/not_implemented_exception.h>
-#include <hicn/transport/utils/log.h>
#include <io_modules/forwarder/forwarder_module.h>
namespace transport {
@@ -36,8 +36,8 @@ bool ForwarderModule::isConnected() { return true; }
void ForwarderModule::send(Packet &packet) {
IoModule::send(packet);
forwarder_.send(packet);
- // TRANSPORT_LOGD("ForwarderModule: sending from %u to %d", local_id_,
- // 1 - local_id_);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Sending from " << connector_id_ << " to " << 1 - connector_id_;
// local_faces_.at(1 - local_id_).onPacket(packet);
}
diff --git a/libtransport/src/io_modules/forwarder/global_id_counter.h b/libtransport/src/io_modules/forwarder/global_id_counter.h
index fe8d76730..0a67b76d5 100644
--- a/libtransport/src/io_modules/forwarder/global_id_counter.h
+++ b/libtransport/src/io_modules/forwarder/global_id_counter.h
@@ -15,6 +15,8 @@
#pragma once
+#include <hicn/transport/utils/singleton.h>
+
#include <atomic>
#include <mutex>
@@ -23,32 +25,15 @@ namespace transport {
namespace core {
template <typename T = uint64_t>
-class GlobalCounter {
+class GlobalCounter : public utils::Singleton<GlobalCounter<T>> {
public:
- static GlobalCounter& getInstance() {
- std::lock_guard<std::mutex> lock(global_mutex_);
-
- if (!instance_) {
- instance_.reset(new GlobalCounter());
- }
-
- return *instance_;
- }
-
+ friend class utils::Singleton<GlobalCounter>;
T getNext() { return counter_++; }
private:
GlobalCounter() : counter_(0) {}
- static std::unique_ptr<GlobalCounter<T>> instance_;
- static std::mutex global_mutex_;
std::atomic<T> counter_;
};
-template <typename T>
-std::unique_ptr<GlobalCounter<T>> GlobalCounter<T>::instance_ = nullptr;
-
-template <typename T>
-std::mutex GlobalCounter<T>::global_mutex_;
-
} // namespace core
} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel.cc b/libtransport/src/io_modules/forwarder/udp_tunnel.cc
index dc725fc4e..bf6a69b92 100644
--- a/libtransport/src/io_modules/forwarder/udp_tunnel.cc
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel.cc
@@ -2,6 +2,7 @@
* Copyright (c) 2017-2019 Cisco and/or its affiliates.
*/
+#include <glog/logging.h>
#include <hicn/transport/utils/branch_prediction.h>
#include <io_modules/forwarder/errors.h>
#include <io_modules/forwarder/udp_tunnel.h>
@@ -62,7 +63,7 @@ void UdpTunnelConnector::send(Packet &packet) {
void UdpTunnelConnector::send(const uint8_t *packet, std::size_t len) {}
void UdpTunnelConnector::close() {
- TRANSPORT_LOGD("UDPTunnelConnector::close");
+ DLOG_IF(INFO, VLOG_IS_ON(2)) << "UDPTunnelConnector::close";
state_ = State::CLOSED;
bool is_socket_owned = socket_.use_count() == 1;
if (is_socket_owned) {
@@ -150,8 +151,8 @@ void UdpTunnelConnector::writeHandler(std::error_code ec) {
output_buffer_.pop_front();
}
} else if (retval != EWOULDBLOCK && retval != EAGAIN) {
- TRANSPORT_LOGE("Error sending messages! %s %d\n", strerror(errno),
- retval);
+ LOG(ERROR) << "Error sending messages! " << strerror(errno)
+ << " << retval";
return;
}
}
@@ -164,9 +165,8 @@ void UdpTunnelConnector::writeHandler(std::error_code ec) {
}
void UdpTunnelConnector::readHandler(std::error_code ec) {
- TRANSPORT_LOGD("UdpTunnelConnector receive packet");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
- // TRANSPORT_LOGD("UdpTunnelConnector received packet length=%lu", length);
if (TRANSPORT_EXPECT_TRUE(!ec)) {
if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
if (current_position_ == 0) {
@@ -182,8 +182,8 @@ void UdpTunnelConnector::readHandler(std::error_code ec) {
int res = recvmmsg(socket_->native_handle(), rx_msgs_ + current_position_,
max_burst - current_position_, MSG_DONTWAIT, nullptr);
if (res < 0) {
- TRANSPORT_LOGE("Error receiving messages! %s %d\n", strerror(errno),
- res);
+ LOG(ERROR) << "Error receiving messages! " << strerror(errno) << " "
+ << res;
return;
}
@@ -200,19 +200,20 @@ void UdpTunnelConnector::readHandler(std::error_code ec) {
doRecvPacket();
} else {
- TRANSPORT_LOGE(
- "Error in UDP: Receiving packets from a not connected socket.");
+ LOG(ERROR)
+ << "Error in UDP: Receiving packets from a not connected socket.";
}
} else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
- TRANSPORT_LOGE("The connection has been closed by the application.");
+ LOG(ERROR) << "The connection has been closed by the application.";
return;
} else {
if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
// receive_callback_(this, *read_msg_, ec);
- TRANSPORT_LOGE("Error in UDP connector: %d %s", ec.value(),
- ec.message().c_str());
+ LOG(ERROR) << "Error in UDP connector: " << ec.value() << " "
+ << ec.message();
} else {
- TRANSPORT_LOGE("Error while not connector");
+ LOG(ERROR) << "Error in connector while not connected. " << ec.value()
+ << " " << ec.message();
}
}
}
@@ -226,16 +227,17 @@ void UdpTunnelConnector::doRecvPacket() {
#else
socket_->async_wait(asio::ip::tcp::socket::wait_read,
#endif
- std::bind(&UdpTunnelConnector::readHandler, this,
- std::placeholders::_1));
+ std::bind(&UdpTunnelConnector::readHandler, this,
+ std::placeholders::_1));
}
#else
- TRANSPORT_LOGD("UdpTunnelConnector receive packet");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
read_msg_ = getRawBuffer();
socket_->async_receive_from(
asio::buffer(read_msg_.first, read_msg_.second), remote_endpoint_recv_,
[this](std::error_code ec, std::size_t length) {
- TRANSPORT_LOGD("UdpTunnelConnector received packet length=%lu", length);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "UdpTunnelConnector received packet length=" << length;
if (TRANSPORT_EXPECT_TRUE(!ec)) {
if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
auto packet = getPacketFromBuffer(read_msg_.first, length);
@@ -244,19 +246,19 @@ void UdpTunnelConnector::doRecvPacket() {
make_error_code(forwarder_error::success));
doRecvPacket();
} else {
- TRANSPORT_LOGE(
- "Error in UDP: Receiving packets from a not connected socket.");
+ LOG(ERROR) << "Error in UDP: Receiving packets from a not "
+ "connected socket.";
}
} else if (ec.value() ==
static_cast<int>(std::errc::operation_canceled)) {
- TRANSPORT_LOGE("The connection has been closed by the application.");
+ LOG(ERROR) << "The connection has been closed by the application.";
return;
} else {
if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
- TRANSPORT_LOGE("Error in UDP connector: %d %s", ec.value(),
- ec.message().c_str());
+ LOG(ERROR) << "Error in UDP connector: " << ec.value()
+ << ec.message();
} else {
- TRANSPORT_LOGE("Error while not connector");
+ LOG(ERROR) << "Error while not connected";
}
}
});
@@ -276,7 +278,7 @@ void UdpTunnelConnector::doConnect() {
doSendPacket();
}
} else {
- TRANSPORT_LOGE("[Hproxy] - UDP Connection failed!!!");
+ LOG(ERROR) << "UDP Connection failed!!!";
timer_.expires_from_now(std::chrono::milliseconds(500));
timer_.async_wait(std::bind(&UdpTunnelConnector::doConnect, this));
}
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel.h b/libtransport/src/io_modules/forwarder/udp_tunnel.h
index df472af91..4f044f93f 100644
--- a/libtransport/src/io_modules/forwarder/udp_tunnel.h
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel.h
@@ -4,12 +4,11 @@
#pragma once
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/portability/platform.h>
#include <io_modules/forwarder/errors.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <iostream>
#include <memory>
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc
index 12246c3cf..d047cc568 100644
--- a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc
@@ -2,8 +2,8 @@
* Copyright (c) 2017-2019 Cisco and/or its affiliates.
*/
+#include <glog/logging.h>
#include <hicn/transport/utils/hash.h>
-#include <hicn/transport/utils/log.h>
#include <io_modules/forwarder/udp_tunnel.h>
#include <io_modules/forwarder/udp_tunnel_listener.h>
@@ -36,9 +36,8 @@ void UdpTunnelListener::close() {
#ifdef LINUX
void UdpTunnelListener::readHandler(std::error_code ec) {
- TRANSPORT_LOGD("UdpTunnelConnector receive packet");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "UdpTunnelConnector receive packet";
- // TRANSPORT_LOGD("UdpTunnelConnector received packet length=%lu", length);
if (TRANSPORT_EXPECT_TRUE(!ec)) {
if (current_position_ == 0) {
for (int i = 0; i < Connector::max_burst; i++) {
@@ -56,7 +55,8 @@ void UdpTunnelListener::readHandler(std::error_code ec) {
Connector::max_burst - current_position_, MSG_DONTWAIT,
nullptr);
if (res < 0) {
- TRANSPORT_LOGE("Error in recvmmsg.");
+ LOG(ERROR) << "Error in recvmmsg.";
+ return;
}
for (int i = 0; i < res; i++) {
@@ -119,10 +119,10 @@ void UdpTunnelListener::readHandler(std::error_code ec) {
doRecvPacket();
} else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
- TRANSPORT_LOGE("The connection has been closed by the application.");
+ LOG(ERROR) << "The connection has been closed by the application.";
return;
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
}
}
#endif
@@ -165,10 +165,10 @@ void UdpTunnelListener::doRecvPacket() {
doRecvPacket();
} else if (ec.value() ==
static_cast<int>(std::errc::operation_canceled)) {
- TRANSPORT_LOGE("The connection has been closed by the application.");
+ LOG(ERROR) << "The connection has been closed by the application.";
return;
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
}
});
#endif
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h
index 0ee40a400..5d197dcb0 100644
--- a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h
@@ -4,11 +4,10 @@
#pragma once
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/portability/platform.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <unordered_map>
namespace std {
diff --git a/libtransport/src/io_modules/loopback/CMakeLists.txt b/libtransport/src/io_modules/loopback/CMakeLists.txt
index ac6dc8068..b5ae0b7f7 100644
--- a/libtransport/src/io_modules/loopback/CMakeLists.txt
+++ b/libtransport/src/io_modules/loopback/CMakeLists.txt
@@ -11,9 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-
list(APPEND MODULE_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/loopback_module.h
)
@@ -26,9 +23,8 @@ build_module(loopback_module
SHARED
SOURCES ${MODULE_SOURCE_FILES}
DEPENDS ${DEPENDENCIES}
- COMPONENT lib${LIBTRANSPORT}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- # LIBRARY_ROOT_DIR "vpp_plugins"
DEFINITIONS ${COMPILER_DEFINITIONS}
COMPILE_OPTIONS ${COMPILE_FLAGS}
)
diff --git a/libtransport/src/io_modules/loopback/local_face.cc b/libtransport/src/io_modules/loopback/local_face.cc
index a59dab235..b73444330 100644
--- a/libtransport/src/io_modules/loopback/local_face.cc
+++ b/libtransport/src/io_modules/loopback/local_face.cc
@@ -13,13 +13,12 @@
* limitations under the License.
*/
+#include <glog/logging.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
-#include <hicn/transport/utils/log.h>
#include <io_modules/loopback/local_face.h>
-#include <asio/io_service.hpp>
-
namespace transport {
namespace core {
@@ -56,7 +55,7 @@ Face &Face::operator=(Face &&other) {
}
void Face::onPacket(const Packet &packet) {
- TRANSPORT_LOGD("Sending content to local socket.");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending content to local socket.";
if (Packet::isInterest(packet.data())) {
rescheduleOnIoService<Interest>(packet);
diff --git a/libtransport/src/io_modules/loopback/local_face.h b/libtransport/src/io_modules/loopback/local_face.h
index 1cbcc2c72..1f4101447 100644
--- a/libtransport/src/io_modules/loopback/local_face.h
+++ b/libtransport/src/io_modules/loopback/local_face.h
@@ -15,12 +15,11 @@
#pragma once
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/core/global_object_pool.h>
#include <hicn/transport/utils/move_wrapper.h>
-#include <asio/io_service.hpp>
-
namespace transport {
namespace core {
diff --git a/libtransport/src/io_modules/loopback/loopback_module.cc b/libtransport/src/io_modules/loopback/loopback_module.cc
index 0bdbf8c8e..f7dd5e7b0 100644
--- a/libtransport/src/io_modules/loopback/loopback_module.cc
+++ b/libtransport/src/io_modules/loopback/loopback_module.cc
@@ -13,8 +13,8 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/errors/not_implemented_exception.h>
-#include <hicn/transport/utils/log.h>
#include <io_modules/loopback/loopback_module.h>
namespace transport {
@@ -35,8 +35,8 @@ bool LoopbackModule::isConnected() { return true; }
void LoopbackModule::send(Packet &packet) {
IoModule::send(packet);
- TRANSPORT_LOGD("LoopbackModule: sending from %u to %d", local_id_,
- 1 - local_id_);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "LoopbackModule: sending from " << local_id_
+ << " to " << 1 - local_id_;
local_faces_.at(1 - local_id_)->send(packet);
}
diff --git a/libtransport/src/io_modules/memif/CMakeLists.txt b/libtransport/src/io_modules/memif/CMakeLists.txt
index c8a930e7b..fc1c1f135 100644
--- a/libtransport/src/io_modules/memif/CMakeLists.txt
+++ b/libtransport/src/io_modules/memif/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
find_package(Vpp REQUIRED)
find_package(Libmemif REQUIRED)
@@ -43,7 +41,7 @@ build_module(memif_module
SHARED
SOURCES ${MODULE_SOURCE_FILES}
DEPENDS ${DEPENDENCIES}
- COMPONENT lib${LIBTRANSPORT}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}-io-modules
LINK_LIBRARIES ${LIBMEMIF_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
INCLUDE_DIRS
${LIBTRANSPORT_INCLUDE_DIRS}
diff --git a/libtransport/src/io_modules/memif/hicn_vapi.c b/libtransport/src/io_modules/memif/hicn_vapi.c
index b83a36b47..6d78026ab 100644
--- a/libtransport/src/io_modules/memif/hicn_vapi.c
+++ b/libtransport/src/io_modules/memif/hicn_vapi.c
@@ -14,7 +14,6 @@
*/
#include <hicn/transport/config.h>
-#include <hicn/transport/utils/log.h>
#include <io_modules/memif/hicn_vapi.h>
#define HICN_VPP_PLUGIN
diff --git a/libtransport/src/io_modules/memif/memif_connector.cc b/libtransport/src/io_modules/memif/memif_connector.cc
index 4a688d68f..68ad52b63 100644
--- a/libtransport/src/io_modules/memif/memif_connector.cc
+++ b/libtransport/src/io_modules/memif/memif_connector.cc
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/errors/not_implemented_exception.h>
#include <io_modules/memif/memif_connector.h>
#include <sys/epoll.h>
@@ -66,6 +67,7 @@ MemifConnector::MemifConnector(PacketReceivedCallback &&receive_callback,
disconnect_timer_(
std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
io_service_(io_service),
+ work_(asio::make_work_guard(io_service_)),
memif_connection_(std::make_unique<memif_connection_t>()),
tx_buf_counter_(0),
is_reconnection_(false),
@@ -83,7 +85,7 @@ void MemifConnector::init() {
nullptr, nullptr, nullptr);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_init: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_init: " << memif_strerror(err);
}
}
@@ -95,8 +97,6 @@ void MemifConnector::connect(uint32_t memif_id, long memif_mode) {
createMemif(memif_id, memif_mode, nullptr);
- work_ = std::make_unique<asio::io_service::work>(io_service_);
-
while (state_ != State::CONNECTED) {
MemifConnector::main_event_reactor_.runOneEvent();
}
@@ -107,7 +107,7 @@ void MemifConnector::connect(uint32_t memif_id, long memif_mode) {
int fd = -1;
err = memif_get_queue_efd(memif_connection_->conn, 0, &fd);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_get_queue_efd: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_get_queue_efd: " << memif_strerror(err);
return;
}
@@ -198,11 +198,11 @@ int MemifConnector::deleteMemif() {
err = memif_delete(&c->conn);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_delete: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_delete: " << memif_strerror(err);
}
if (TRANSPORT_EXPECT_FALSE(c->conn != nullptr)) {
- TRANSPORT_LOGE("memif delete fail");
+ LOG(ERROR) << "memif delete fail";
}
return 0;
@@ -248,8 +248,8 @@ int MemifConnector::controlFdUpdate(int fd, uint8_t events, void *private_ctx) {
memif_err = memif_control_fd_handler(evt.data.fd, event);
if (TRANSPORT_EXPECT_FALSE(memif_err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_control_fd_handler: %s",
- memif_strerror(memif_err));
+ LOG(ERROR) << "memif_control_fd_handler: "
+ << memif_strerror(memif_err);
}
return 0;
@@ -265,7 +265,7 @@ int MemifConnector::bufferAlloc(long n, uint16_t qid) {
err = memif_buffer_alloc(c->conn, qid, c->tx_bufs, n, &r, 2000);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_buffer_alloc: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_buffer_alloc: " << memif_strerror(err);
return -1;
}
@@ -282,13 +282,13 @@ int MemifConnector::txBurst(uint16_t qid) {
err = memif_tx_burst(c->conn, qid, c->tx_bufs, c->tx_buf_num, &r);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_tx_burst: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_tx_burst: " << memif_strerror(err);
}
// err = memif_refill_queue(c->conn, qid, r, 0);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_tx_burst: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_tx_burst: " << memif_strerror(err);
c->tx_buf_num -= r;
return -1;
}
@@ -350,14 +350,14 @@ int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS &&
err != MEMIF_ERR_NOBUF)) {
- TRANSPORT_LOGE("memif_rx_burst: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_rx_burst: " << memif_strerror(err);
goto error;
}
c->rx_buf_num += rx;
if (TRANSPORT_EXPECT_FALSE(connector->io_service_.stopped())) {
- TRANSPORT_LOGE("socket stopped: ignoring %u packets", rx);
+ LOG(ERROR) << "socket stopped: ignoring " << rx << " packets";
goto error;
}
@@ -369,7 +369,7 @@ int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
auto packet = connector->getPacketFromBuffer(buffer.first, packet_length);
if (!connector->input_buffer_.push(std::move(packet))) {
- TRANSPORT_LOGE("Error pushing packet. Ring buffer full.");
+ LOG(ERROR) << "Error pushing packet. Ring buffer full.";
// TODO Here we should consider the possibility to signal the congestion
// to the application, that would react properly (e.g. slow down
@@ -383,7 +383,7 @@ int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
err = memif_refill_queue(conn, qid, rx, 0);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_buffer_free: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
}
c->rx_buf_num -= rx;
@@ -400,7 +400,7 @@ error:
err = memif_refill_queue(c->conn, qid, rx, 0);
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- TRANSPORT_LOGE("memif_buffer_free: %s", memif_strerror(err));
+ LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
}
c->rx_buf_num -= rx;
@@ -413,7 +413,6 @@ void MemifConnector::close() {
disconnect_timer_->asyncWait([this](const std::error_code &ec) {
deleteMemif();
event_reactor_.stop();
- work_.reset();
});
if (memif_worker_ && memif_worker_->joinable()) {
@@ -452,7 +451,7 @@ int MemifConnector::doSend() {
n = bufferAlloc(max, memif_connection_->tx_qid);
if (TRANSPORT_EXPECT_FALSE(n < 0)) {
- TRANSPORT_LOGE("Error allocating buffers.");
+ LOG(ERROR) << "Error allocating buffers.";
return -1;
}
diff --git a/libtransport/src/io_modules/memif/memif_connector.h b/libtransport/src/io_modules/memif/memif_connector.h
index bed3516dc..0a189f893 100644
--- a/libtransport/src/io_modules/memif/memif_connector.h
+++ b/libtransport/src/io_modules/memif/memif_connector.h
@@ -20,10 +20,10 @@
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/ring_buffer.h>
//#include <hicn/transport/core/hicn_vapi.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <utils/epoll_event_reactor.h>
#include <utils/fd_deadline_timer.h>
-#include <asio.hpp>
#include <deque>
#include <mutex>
#include <thread>
@@ -108,7 +108,7 @@ class MemifConnector : public Connector {
std::unique_ptr<utils::FdDeadlineTimer> send_timer_;
std::unique_ptr<utils::FdDeadlineTimer> disconnect_timer_;
asio::io_service &io_service_;
- std::unique_ptr<asio::io_service::work> work_;
+ asio::executor_work_guard<asio::io_context::executor_type> work_;
std::unique_ptr<memif_connection_t> memif_connection_;
uint16_t tx_buf_counter_;
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
index dcbcd7ed0..44c8376df 100644
--- a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/config.h>
#include <hicn/transport/errors/not_implemented_exception.h>
#include <io_modules/memif/hicn_vapi.h>
@@ -148,21 +149,19 @@ void VPPForwarderModule::producerConnection() {
void VPPForwarderModule::connect(bool is_consumer) {
int retry = 20;
- TRANSPORT_LOGI("Connecting to VPP through vapi.");
+ LOG(INFO) << "Connecting to VPP through vapi.";
vapi_error_e ret = vapi_connect_safe(&sock_, 0);
while (ret != VAPI_OK && retry > 0) {
- TRANSPORT_LOGE("Error connecting to VPP through vapi. Retrying..");
+ LOG(ERROR) << "Error connecting to VPP through vapi. Retrying..";
--retry;
ret = vapi_connect_safe(&sock_, 0);
}
- if (ret != VAPI_OK) {
- throw std::runtime_error(
- "Impossible to connect to forwarder. Is VPP running?");
- }
+ CHECK_EQ(ret, VAPI_OK)
+ << "Impossible to connect to forwarder. Is VPP running?";
- TRANSPORT_LOGI("Connected to VPP through vapi.");
+ LOG(INFO) << "Connected to VPP through vapi.";
sw_if_index_ = getMemifConfiguration();
@@ -247,7 +246,7 @@ void VPPForwarderModule::closeConnection() {
int ret =
memif_vapi_delete_memif(VPPForwarderModule::sock_, sw_if_index_);
if (ret < 0) {
- TRANSPORT_LOGE("Error deleting memif with sw idx %u.", sw_if_index_);
+ LOG(ERROR) << "Error deleting memif with sw idx " << sw_if_index_;
}
}
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc b/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc
index 0bfcc2a58..62efdc3a5 100644
--- a/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc
+++ b/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc
@@ -15,7 +15,6 @@
#include <core/raw_socket_connector.h>
#include <hicn/transport/utils/conversions.h>
-#include <hicn/transport/utils/log.h>
#include <net/if.h>
#include <netdb.h>
#include <stdio.h>
@@ -165,7 +164,7 @@ void RawSocketConnector::doSendPacket() {
doSendPacket();
}
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
}
});
}
@@ -185,7 +184,7 @@ void RawSocketConnector::doRecvPacket() {
receive_callback_(std::move(read_msg_));
}
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
}
doRecvPacket();
});
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_connector.h b/libtransport/src/io_modules/raw_socket/raw_socket_connector.h
index aba4b1105..06892b3d8 100644
--- a/libtransport/src/io_modules/raw_socket/raw_socket_connector.h
+++ b/libtransport/src/io_modules/raw_socket/raw_socket_connector.h
@@ -17,13 +17,12 @@
#include <core/connector.h>
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/name.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <sys/socket.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <deque>
namespace transport {
diff --git a/libtransport/src/io_modules/udp/CMakeLists.txt b/libtransport/src/io_modules/udp/CMakeLists.txt
index 93518d0a2..b9c19d063 100644
--- a/libtransport/src/io_modules/udp/CMakeLists.txt
+++ b/libtransport/src/io_modules/udp/CMakeLists.txt
@@ -11,9 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
-
list(APPEND MODULE_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.h
${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.h
@@ -24,23 +21,12 @@ list(APPEND MODULE_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.cc
)
-# add_executable(hicnlight_module MACOSX_BUNDLE ${MODULE_SOURCE_FILES})
-# target_include_directories(hicnlight_module PRIVATE ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS})
-# set_target_properties(hicnlight_module PROPERTIES
-# BUNDLE True
-# MACOSX_BUNDLE_GUI_IDENTIFIER my.domain.style.identifier.hicnlight_module
-# MACOSX_BUNDLE_BUNDLE_NAME hicnlight_module
-# MACOSX_BUNDLE_BUNDLE_VERSION "0.1"
-# MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1"
-# # MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/customtemplate.plist.in
-# )
build_module(hicnlight_module
- SHARED
- SOURCES ${MODULE_SOURCE_FILES}
- DEPENDS ${DEPENDENCIES}
- COMPONENT lib${LIBTRANSPORT}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- # LIBRARY_ROOT_DIR "vpp_plugins"
- DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
+ SHARED
+ SOURCES ${MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILE_FLAGS}
)
diff --git a/libtransport/src/io_modules/udp/udp_socket_connector.cc b/libtransport/src/io_modules/udp/udp_socket_connector.cc
index 456886a54..1412d8c07 100644
--- a/libtransport/src/io_modules/udp/udp_socket_connector.cc
+++ b/libtransport/src/io_modules/udp/udp_socket_connector.cc
@@ -17,8 +17,8 @@
#include <hicn/transport/portability/win_portability.h>
#endif
+#include <glog/logging.h>
#include <hicn/transport/errors/errors.h>
-#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/object_pool.h>
#include <io_modules/udp/udp_socket_connector.h>
@@ -117,7 +117,7 @@ void UdpSocketConnector::doWrite() {
// The connection has been closed by the application.
return;
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
tryReconnect();
}
});
@@ -137,7 +137,7 @@ void UdpSocketConnector::doRead() {
// The connection has been closed by the application.
return;
} else {
- TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ LOG(ERROR) << ec.value() << " " << ec.message();
tryReconnect();
}
});
@@ -145,7 +145,7 @@ void UdpSocketConnector::doRead() {
void UdpSocketConnector::tryReconnect() {
if (state_ == Connector::State::CONNECTED) {
- TRANSPORT_LOGE("Connection lost. Trying to reconnect...\n");
+ LOG(ERROR) << "Connection lost. Trying to reconnect...";
state_ = Connector::State::CONNECTING;
is_reconnection_ = true;
io_service_.post([this]() {
@@ -201,7 +201,7 @@ void UdpSocketConnector::handleDeadline(const std::error_code &ec) {
if (!ec) {
io_service_.post([this]() {
socket_.close();
- TRANSPORT_LOGE("Error connecting. Is the forwarder running?\n");
+ LOG(ERROR) << "Error connecting. Is the forwarder running?";
});
}
}
diff --git a/libtransport/src/io_modules/udp/udp_socket_connector.h b/libtransport/src/io_modules/udp/udp_socket_connector.h
index 8ab08e17a..c483e14aa 100644
--- a/libtransport/src/io_modules/udp/udp_socket_connector.h
+++ b/libtransport/src/io_modules/udp/udp_socket_connector.h
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/global_object_pool.h>
@@ -24,8 +25,6 @@
#include <hicn/transport/core/packet.h>
#include <hicn/transport/utils/branch_prediction.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <deque>
namespace transport {
diff --git a/libtransport/src/protocols/CMakeLists.txt b/libtransport/src/protocols/CMakeLists.txt
index eba8d1aab..b763e95e2 100644
--- a/libtransport/src/protocols/CMakeLists.txt
+++ b/libtransport/src/protocols/CMakeLists.txt
@@ -11,12 +11,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/indexer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/incremental_indexer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/manifest_incremental_indexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/incremental_indexer_bytestream.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/manifest_incremental_indexer_bytestream.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/index_manager_bytestream.h
${CMAKE_CURRENT_SOURCE_DIR}/reassembly.h
${CMAKE_CURRENT_SOURCE_DIR}/datagram_reassembly.h
${CMAKE_CURRENT_SOURCE_DIR}/byte_stream_reassembly.h
@@ -31,12 +30,14 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/cbr.h
${CMAKE_CURRENT_SOURCE_DIR}/errors.h
${CMAKE_CURRENT_SOURCE_DIR}/data_processing_events.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/fec_base.h
)
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/indexer.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/incremental_indexer.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/manifest_incremental_indexer.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/incremental_indexer_bytestream.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/manifest_incremental_indexer_bytestream.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/index_manager_bytestream.cc
${CMAKE_CURRENT_SOURCE_DIR}/reassembly.cc
${CMAKE_CURRENT_SOURCE_DIR}/datagram_reassembly.cc
${CMAKE_CURRENT_SOURCE_DIR}/byte_stream_reassembly.cc
@@ -67,10 +68,11 @@ set(TRANSPORT_CONFIG
install(
FILES ${TRANSPORT_CONFIG}
DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
- COMPONENT lib${LIBTRANSPORT}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
)
add_subdirectory(rtc)
+add_subdirectory(fec)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/protocols/byte_stream_reassembly.cc b/libtransport/src/protocols/byte_stream_reassembly.cc
index d2bc961c4..ac36d4e61 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.cc
+++ b/libtransport/src/protocols/byte_stream_reassembly.cc
@@ -33,7 +33,7 @@ ByteStreamReassembly::ByteStreamReassembly(
implementation::ConsumerSocket *icn_socket,
TransportProtocol *transport_protocol)
: Reassembly(icn_socket, transport_protocol),
- index_(IndexManager::invalid_index),
+ index_(Indexer::invalid_index),
download_complete_(false) {}
void ByteStreamReassembly::reassemble(
@@ -54,10 +54,14 @@ void ByteStreamReassembly::reassemble(ContentObject &content_object) {
}
}
+void ByteStreamReassembly::reassemble(utils::MemBuf &buffer, uint32_t suffix) {
+ throw errors::NotImplementedException();
+}
+
void ByteStreamReassembly::assembleContent() {
- if (TRANSPORT_EXPECT_FALSE(index_ == IndexManager::invalid_index)) {
- index_ = index_manager_->getNextReassemblySegment();
- if (index_ == IndexManager::invalid_index) {
+ if (TRANSPORT_EXPECT_FALSE(index_ == Indexer::invalid_index)) {
+ index_ = indexer_verifier_->getNextReassemblySegment();
+ if (index_ == Indexer::invalid_index) {
return;
}
}
@@ -72,11 +76,11 @@ void ByteStreamReassembly::assembleContent() {
}
received_packets_.erase(it);
- index_ = index_manager_->getNextReassemblySegment();
+ index_ = indexer_verifier_->getNextReassemblySegment();
it = received_packets_.find((const unsigned int)index_);
}
- if (!download_complete_ && index_ != IndexManager::invalid_index) {
+ if (!download_complete_ && index_ != Indexer::invalid_index) {
transport_protocol_->onReassemblyFailed(index_);
}
}
@@ -108,8 +112,8 @@ bool ByteStreamReassembly::copyContent(ContentObject &content_object) {
current = current->next();
} while (current != &content_object);
- download_complete_ =
- index_manager_->getFinalSuffix() == content_object.getName().getSuffix();
+ download_complete_ = indexer_verifier_->getFinalSuffix() ==
+ content_object.getName().getSuffix();
if (TRANSPORT_EXPECT_FALSE(download_complete_)) {
ret = download_complete_;
@@ -122,17 +126,19 @@ bool ByteStreamReassembly::copyContent(ContentObject &content_object) {
}
void ByteStreamReassembly::reInitialize() {
- index_ = IndexManager::invalid_index;
+ index_ = Indexer::invalid_index;
download_complete_ = false;
received_packets_.clear();
// reset read buffer
ReadCallback *read_callback;
- reassembly_consumer_socket_->getSocketOption(
- interface::ConsumerCallbacksOptions::READ_CALLBACK, &read_callback);
- read_buffer_ = utils::MemBuf::create(read_callback->maxBufferSize());
+ if (reassembly_consumer_socket_) {
+ reassembly_consumer_socket_->getSocketOption(
+ interface::ConsumerCallbacksOptions::READ_CALLBACK, &read_callback);
+ read_buffer_ = utils::MemBuf::create(read_callback->maxBufferSize());
+ }
}
} // namespace protocol
diff --git a/libtransport/src/protocols/byte_stream_reassembly.h b/libtransport/src/protocols/byte_stream_reassembly.h
index c682d58cb..278740bd3 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.h
+++ b/libtransport/src/protocols/byte_stream_reassembly.h
@@ -27,11 +27,13 @@ class ByteStreamReassembly : public Reassembly {
TransportProtocol *transport_protocol);
protected:
- virtual void reassemble(core::ContentObject &content_object) override;
+ void reassemble(core::ContentObject &content_object) override;
- virtual void reassemble(
+ void reassemble(
std::unique_ptr<core::ContentObjectManifest> &&manifest) override;
+ void reassemble(utils::MemBuf &buffer, uint32_t suffix) override;
+
bool copyContent(core::ContentObject &content_object);
virtual void reInitialize() override;
@@ -40,10 +42,6 @@ class ByteStreamReassembly : public Reassembly {
void assembleContent();
protected:
- // The consumer socket
- // std::unique_ptr<IncrementalIndexManager> incremental_index_manager_;
- // std::unique_ptr<ManifestIndexManager> manifest_index_manager_;
- // IndexVerificationManager *index_manager_;
std::unordered_map<std::uint32_t, core::ContentObject::Ptr> received_packets_;
uint32_t index_;
bool download_complete_;
diff --git a/libtransport/src/protocols/cbr.cc b/libtransport/src/protocols/cbr.cc
index 0bffd7d18..1548cc68d 100644
--- a/libtransport/src/protocols/cbr.cc
+++ b/libtransport/src/protocols/cbr.cc
@@ -26,8 +26,6 @@ CbrTransportProtocol::CbrTransportProtocol(
implementation::ConsumerSocket *icnet_socket)
: RaaqmTransportProtocol(icnet_socket) {}
-int CbrTransportProtocol::start() { return RaaqmTransportProtocol::start(); }
-
void CbrTransportProtocol::reset() {
RaaqmTransportProtocol::reset();
socket_->getSocketOption(GeneralTransportOptions::CURRENT_WINDOW_SIZE,
diff --git a/libtransport/src/protocols/cbr.h b/libtransport/src/protocols/cbr.h
index 20129f6a3..41cdbc98c 100644
--- a/libtransport/src/protocols/cbr.h
+++ b/libtransport/src/protocols/cbr.h
@@ -25,7 +25,8 @@ class CbrTransportProtocol : public RaaqmTransportProtocol {
public:
CbrTransportProtocol(implementation::ConsumerSocket *icnet_socket);
- int start() override;
+ using RaaqmTransportProtocol::start;
+ using RaaqmTransportProtocol::stop;
void reset() override;
diff --git a/libtransport/src/protocols/data_processing_events.h b/libtransport/src/protocols/data_processing_events.h
index 5c8c16157..28732502b 100644
--- a/libtransport/src/protocols/data_processing_events.h
+++ b/libtransport/src/protocols/data_processing_events.h
@@ -24,7 +24,8 @@ namespace protocol {
class ContentObjectProcessingEventCallback {
public:
virtual ~ContentObjectProcessingEventCallback() = default;
- virtual void onPacketDropped(core::Interest &i, core::ContentObject &c) = 0;
+ virtual void onPacketDropped(core::Interest &i, core::ContentObject &c,
+ const std::error_code &reason) = 0;
virtual void onReassemblyFailed(std::uint32_t missing_segment) = 0;
};
diff --git a/libtransport/src/protocols/datagram_reassembly.cc b/libtransport/src/protocols/datagram_reassembly.cc
index 962c1e020..069873a52 100644
--- a/libtransport/src/protocols/datagram_reassembly.cc
+++ b/libtransport/src/protocols/datagram_reassembly.cc
@@ -14,6 +14,7 @@
*/
#include <protocols/datagram_reassembly.h>
+#include <protocols/transport_protocol.h>
namespace transport {
@@ -25,7 +26,17 @@ DatagramReassembly::DatagramReassembly(
: Reassembly(icn_socket, transport_protocol) {}
void DatagramReassembly::reassemble(core::ContentObject& content_object) {
- read_buffer_ = content_object.getPayload();
+ auto read_buffer = content_object.getPayload();
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Size of payload: " << read_buffer->length() << ". Trimming "
+ << transport_protocol_->transportHeaderLength();
+ read_buffer->trimStart(transport_protocol_->transportHeaderLength());
+ Reassembly::read_buffer_ = std::move(read_buffer);
+ Reassembly::notifyApplication();
+}
+
+void DatagramReassembly::reassemble(utils::MemBuf& buffer, uint32_t suffix) {
+ read_buffer_ = buffer.cloneOne();
Reassembly::notifyApplication();
}
diff --git a/libtransport/src/protocols/datagram_reassembly.h b/libtransport/src/protocols/datagram_reassembly.h
index 3462212d3..de294df06 100644
--- a/libtransport/src/protocols/datagram_reassembly.h
+++ b/libtransport/src/protocols/datagram_reassembly.h
@@ -27,11 +27,13 @@ class DatagramReassembly : public Reassembly {
TransportProtocol *transport_protocol);
virtual void reassemble(core::ContentObject &content_object) override;
+ void reassemble(utils::MemBuf &buffer, uint32_t suffix) override;
virtual void reInitialize() override;
virtual void reassemble(
std::unique_ptr<core::ContentObjectManifest> &&manifest) override {
return;
}
+ bool reassembleUnverified() override { return true; }
};
} // namespace protocol
diff --git a/libtransport/src/protocols/errors.cc b/libtransport/src/protocols/errors.cc
index ae7b6e634..183fcc574 100644
--- a/libtransport/src/protocols/errors.cc
+++ b/libtransport/src/protocols/errors.cc
@@ -39,6 +39,9 @@ std::string protocol_category_impl::message(int ev) const {
case protocol_error::integrity_verification_failed: {
return "Integrity verification failed";
}
+ case protocol_error::verification_failed: {
+ return "Verification failed";
+ }
case protocol_error::no_verifier_provided: {
return "Transport cannot get any verifier for the given data.";
}
@@ -52,6 +55,12 @@ std::string protocol_category_impl::message(int ev) const {
case protocol_error::session_aborted: {
return "The session has been aborted by the application.";
}
+ case protocol_error::not_reassemblable: {
+ return "The session has been aborted by the application.";
+ }
+ case protocol_error::duplicated_content: {
+ return "The session has been aborted by the application.";
+ }
default: {
return "Unknown protocol error";
}
@@ -59,4 +68,4 @@ std::string protocol_category_impl::message(int ev) const {
}
} // namespace protocol
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/protocols/errors.h b/libtransport/src/protocols/errors.h
index cb3d3474e..58dadae5a 100644
--- a/libtransport/src/protocols/errors.h
+++ b/libtransport/src/protocols/errors.h
@@ -37,10 +37,14 @@ enum class protocol_error {
success = 0,
signature_verification_failed,
integrity_verification_failed,
+ verification_failed,
no_verifier_provided,
io_error,
max_retransmissions_error,
session_aborted,
+ not_reassemblable,
+ delayed_reassemble,
+ duplicated_content
};
/**
diff --git a/libtransport/src/security/CMakeLists.txt b/libtransport/src/protocols/fec/CMakeLists.txt
index 0e7b5832b..6d61ae043 100644
--- a/libtransport/src/security/CMakeLists.txt
+++ b/libtransport/src/protocols/fec/CMakeLists.txt
@@ -11,12 +11,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/fec.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rs.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/fec_info.h
+)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/signer.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/verifier.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/identity.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/fec.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rs.cc
)
+if (ENABLE_RELY)
+ list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/rely.h
+ )
+
+ list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/rely.cc
+ )
+endif()
+
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/protocols/fec/fec.cc b/libtransport/src/protocols/fec/fec.cc
new file mode 100644
index 000000000..16a04cb98
--- /dev/null
+++ b/libtransport/src/protocols/fec/fec.cc
@@ -0,0 +1,838 @@
+/*
+ * fec.c -- forward error correction based on Vandermonde matrices
+ * 980624
+ * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
+ *
+ * Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
+ * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
+ * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * The following parameter defines how many bits are used for
+ * field elements. The code supports any value from 2 to 16
+ * but fastest operation is achieved with 8 bit elements
+ * This is the only parameter you may want to change.
+ */
+#ifndef GF_BITS
+#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */
+#endif
+
+#include "fec.h"
+
+#include <hicn/transport/portability/platform.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * XXX This disable a warning raising only in some platforms.
+ * TODO Check if this warning is a mistake or it is a real bug:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83404
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=88059
+ */
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
+
+/*
+ * compatibility stuff
+ */
+#ifdef MSDOS /* but also for others, e.g. sun... */
+#define NEED_BCOPY
+#define bcmp(a, b, n) memcmp(a, b, n)
+#endif
+
+#ifdef ANDROID
+#define bcmp(a, b, n) memcmp(a, b, n)
+#endif
+
+#ifdef NEED_BCOPY
+#define bcopy(s, d, siz) memcpy((d), (s), (siz))
+#define bzero(d, siz) memset((d), '\0', (siz))
+#endif
+
+/*
+ * stuff used for testing purposes only
+ */
+
+#ifdef TEST
+#define DEB(x)
+#define DDB(x) x
+#define DEBUG 0 /* minimal debugging */
+#ifdef MSDOS
+#include <time.h>
+struct timeval {
+ unsigned long ticks;
+};
+#define gettimeofday(x, dummy) \
+ { (x)->ticks = clock(); }
+#define DIFF_T(a, b) (1 + 1000000 * (a.ticks - b.ticks) / CLOCKS_PER_SEC)
+typedef unsigned long u_long;
+typedef unsigned short u_short;
+#else /* typically, unix systems */
+#include <sys/time.h>
+#define DIFF_T(a, b) \
+ (1 + 1000000 * (a.tv_sec - b.tv_sec) + (a.tv_usec - b.tv_usec))
+#endif
+
+#define TICK(t) \
+ { \
+ struct timeval x; \
+ gettimeofday(&x, NULL); \
+ t = x.tv_usec + 1000000 * (x.tv_sec & 0xff); \
+ }
+#define TOCK(t) \
+ { \
+ u_long t1; \
+ TICK(t1); \
+ if (t1 < t) \
+ t = 256000000 + t1 - t; \
+ else \
+ t = t1 - t; \
+ if (t == 0) t = 1; \
+ }
+
+u_long ticks[10]; /* vars for timekeeping */
+#else
+#define DEB(x)
+#define DDB(x)
+#define TICK(x)
+#define TOCK(x)
+#endif /* TEST */
+
+/*
+ * You should not need to change anything beyond this point.
+ * The first part of the file implements linear algebra in GF.
+ *
+ * gf is the type used to store an element of the Galois Field.
+ * Must constain at least GF_BITS bits.
+ *
+ * Note: unsigned char will work up to GF(256) but int seems to run
+ * faster on the Pentium. We use int whenever have to deal with an
+ * index, since they are generally faster.
+ */
+#if (GF_BITS < 2 && GF_BITS > 16)
+#error "GF_BITS must be 2 .. 16"
+#endif
+
+#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */
+
+/*
+ * Primitive polynomials - see Lin & Costello, Appendix A,
+ * and Lee & Messerschmitt, p. 453.
+ */
+static const char *allPp[] = {
+ /* GF_BITS polynomial */
+ NULL, /* 0 no code */
+ NULL, /* 1 no code */
+ "111", /* 2 1+x+x^2 */
+ "1101", /* 3 1+x+x^3 */
+ "11001", /* 4 1+x+x^4 */
+ "101001", /* 5 1+x^2+x^5 */
+ "1100001", /* 6 1+x+x^6 */
+ "10010001", /* 7 1 + x^3 + x^7 */
+ "101110001", /* 8 1+x^2+x^3+x^4+x^8 */
+ "1000100001", /* 9 1+x^4+x^9 */
+ "10010000001", /* 10 1+x^3+x^10 */
+ "101000000001", /* 11 1+x^2+x^11 */
+ "1100101000001", /* 12 1+x+x^4+x^6+x^12 */
+ "11011000000001", /* 13 1+x+x^3+x^4+x^13 */
+ "110000100010001", /* 14 1+x+x^6+x^10+x^14 */
+ "1100000000000001", /* 15 1+x+x^15 */
+ "11010000000010001" /* 16 1+x+x^3+x^12+x^16 */
+};
+
+/*
+ * To speed up computations, we have tables for logarithm, exponent
+ * and inverse of a number. If GF_BITS <= 8, we use a table for
+ * multiplication as well (it takes 64K, no big deal even on a PDA,
+ * especially because it can be pre-initialized an put into a ROM!),
+ * otherwhise we use a table of logarithms.
+ * In any case the macro gf_mul(x,y) takes care of multiplications.
+ */
+
+static gf gf_exp[2 * GF_SIZE]; /* index->poly form conversion table */
+static int gf_log[GF_SIZE + 1]; /* Poly->index form conversion table */
+static gf inverse[GF_SIZE + 1]; /* inverse of field elem. */
+ /* inv[\alpha**i]=\alpha**(GF_SIZE-i-1) */
+
+/*
+ * modnn(x) computes x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1,
+ * without a slow divide.
+ */
+static inline gf modnn(int x) {
+ while (x >= GF_SIZE) {
+ x -= GF_SIZE;
+ x = (x >> GF_BITS) + (x & GF_SIZE);
+ }
+ return x;
+}
+
+#define SWAP(a, b, t) \
+ { \
+ t tmp; \
+ tmp = a; \
+ a = b; \
+ b = tmp; \
+ }
+
+/*
+ * gf_mul(x,y) multiplies two numbers. If GF_BITS<=8, it is much
+ * faster to use a multiplication table.
+ *
+ * USE_GF_MULC, GF_MULC0(c) and GF_ADDMULC(x) can be used when multiplying
+ * many numbers by the same constant. In this case the first
+ * call sets the constant, and others perform the multiplications.
+ * A value related to the multiplication is held in a local variable
+ * declared with USE_GF_MULC . See usage in addmul1().
+ */
+#if (GF_BITS <= 8)
+static gf gf_mul_table[GF_SIZE + 1][GF_SIZE + 1];
+
+#define gf_mul(x, y) gf_mul_table[x][y]
+
+#define USE_GF_MULC gf *__gf_mulc_
+#define GF_MULC0(c) __gf_mulc_ = gf_mul_table[c]
+#define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x]
+
+static void init_mul_table() {
+ int i, j;
+ for (i = 0; i < GF_SIZE + 1; i++)
+ for (j = 0; j < GF_SIZE + 1; j++)
+ gf_mul_table[i][j] = gf_exp[modnn(gf_log[i] + gf_log[j])];
+
+ for (j = 0; j < GF_SIZE + 1; j++) gf_mul_table[0][j] = gf_mul_table[j][0] = 0;
+}
+#else /* GF_BITS > 8 */
+static inline gf gf_mul(x, y) {
+ if ((x) == 0 || (y) == 0) return 0;
+
+ return gf_exp[gf_log[x] + gf_log[y]];
+}
+#define init_mul_table()
+
+#define USE_GF_MULC register gf *__gf_mulc_
+#define GF_MULC0(c) __gf_mulc_ = &gf_exp[gf_log[c]]
+#define GF_ADDMULC(dst, x) \
+ { \
+ if (x) dst ^= __gf_mulc_[gf_log[x]]; \
+ }
+#endif
+
+/*
+ * Generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
+ * Lookup tables:
+ * index->polynomial form gf_exp[] contains j= \alpha^i;
+ * polynomial form -> index form gf_log[ j = \alpha^i ] = i
+ * \alpha=x is the primitive element of GF(2^m)
+ *
+ * For efficiency, gf_exp[] has size 2*GF_SIZE, so that a simple
+ * multiplication of two numbers can be resolved without calling modnn
+ */
+
+/*
+ * i use malloc so many times, it is easier to put checks all in
+ * one place.
+ */
+static void *my_malloc(int sz, const char *err_string) {
+ void *p = malloc(sz);
+ if (p == NULL) {
+ fprintf(stderr, "-- malloc failure allocating %s\n", err_string);
+ exit(1);
+ }
+ return p;
+}
+
+#define NEW_GF_MATRIX(rows, cols) \
+ (gf *)my_malloc(rows *cols * sizeof(gf), " ## __LINE__ ## ")
+
+/*
+ * initialize the data structures used for computations in GF.
+ */
+static void generate_gf(void) {
+ int i;
+ gf mask;
+ const char *Pp = allPp[GF_BITS];
+
+ mask = 1; /* x ** 0 = 1 */
+ gf_exp[GF_BITS] = 0; /* will be updated at the end of the 1st loop */
+ /*
+ * first, generate the (polynomial representation of) powers of \alpha,
+ * which are stored in gf_exp[i] = \alpha ** i .
+ * At the same time build gf_log[gf_exp[i]] = i .
+ * The first GF_BITS powers are simply bits shifted to the left.
+ */
+ for (i = 0; i < GF_BITS; i++, mask <<= 1) {
+ gf_exp[i] = mask;
+ gf_log[gf_exp[i]] = i;
+ /*
+ * If Pp[i] == 1 then \alpha ** i occurs in poly-repr
+ * gf_exp[GF_BITS] = \alpha ** GF_BITS
+ */
+ if (Pp[i] == '1') gf_exp[GF_BITS] ^= mask;
+ }
+ /*
+ * now gf_exp[GF_BITS] = \alpha ** GF_BITS is complete, so can als
+ * compute its inverse.
+ */
+ gf_log[gf_exp[GF_BITS]] = GF_BITS;
+ /*
+ * Poly-repr of \alpha ** (i+1) is given by poly-repr of
+ * \alpha ** i shifted left one-bit and accounting for any
+ * \alpha ** GF_BITS term that may occur when poly-repr of
+ * \alpha ** i is shifted.
+ */
+ mask = 1 << (GF_BITS - 1);
+ for (i = GF_BITS + 1; i < GF_SIZE; i++) {
+ if (gf_exp[i - 1] >= mask)
+ gf_exp[i] = gf_exp[GF_BITS] ^ ((gf_exp[i - 1] ^ mask) << 1);
+ else
+ gf_exp[i] = gf_exp[i - 1] << 1;
+ gf_log[gf_exp[i]] = i;
+ }
+ /*
+ * log(0) is not defined, so use a special value
+ */
+ gf_log[0] = GF_SIZE;
+ /* set the extended gf_exp values for fast multiply */
+ for (i = 0; i < GF_SIZE; i++) gf_exp[i + GF_SIZE] = gf_exp[i];
+
+ /*
+ * again special cases. 0 has no inverse. This used to
+ * be initialized to GF_SIZE, but it should make no difference
+ * since noone is supposed to read from here.
+ */
+ inverse[0] = 0;
+ inverse[1] = 1;
+ for (i = 2; i <= GF_SIZE; i++) inverse[i] = gf_exp[GF_SIZE - gf_log[i]];
+}
+
+/*
+ * Various linear algebra operations that i use often.
+ */
+
+/*
+ * addmul() computes dst[] = dst[] + c * src[]
+ * This is used often, so better optimize it! Currently the loop is
+ * unrolled 16 times, a good value for 486 and pentium-class machines.
+ * The case c=0 is also optimized, whereas c=1 is not. These
+ * calls are unfrequent in my typical apps so I did not bother.
+ *
+ * Note that gcc on
+ */
+#define addmul(dst, src, c, sz) \
+ if (c != 0) addmul1(dst, src, c, sz)
+
+#define UNROLL 16 /* 1, 4, 8, 16 */
+static void addmul1(gf *dst1, gf *src1, gf c, int sz) {
+ USE_GF_MULC;
+ gf *dst = dst1, *src = src1;
+ gf *lim = &dst[sz - UNROLL + 1];
+
+ GF_MULC0(c);
+
+#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */
+ for (; dst < lim; dst += UNROLL, src += UNROLL) {
+ GF_ADDMULC(dst[0], src[0]);
+ GF_ADDMULC(dst[1], src[1]);
+ GF_ADDMULC(dst[2], src[2]);
+ GF_ADDMULC(dst[3], src[3]);
+#if (UNROLL > 4)
+ GF_ADDMULC(dst[4], src[4]);
+ GF_ADDMULC(dst[5], src[5]);
+ GF_ADDMULC(dst[6], src[6]);
+ GF_ADDMULC(dst[7], src[7]);
+#endif
+#if (UNROLL > 8)
+ GF_ADDMULC(dst[8], src[8]);
+ GF_ADDMULC(dst[9], src[9]);
+ GF_ADDMULC(dst[10], src[10]);
+ GF_ADDMULC(dst[11], src[11]);
+ GF_ADDMULC(dst[12], src[12]);
+ GF_ADDMULC(dst[13], src[13]);
+ GF_ADDMULC(dst[14], src[14]);
+ GF_ADDMULC(dst[15], src[15]);
+#endif
+ }
+#endif
+ lim += UNROLL - 1;
+ for (; dst < lim; dst++, src++) /* final components */
+ GF_ADDMULC(*dst, *src);
+}
+
+/*
+ * computes C = AB where A is n*k, B is k*m, C is n*m
+ */
+static void matmul(gf *a, gf *b, gf *c, int n, int k, int m) {
+ int row, col, i;
+
+ for (row = 0; row < n; row++) {
+ for (col = 0; col < m; col++) {
+ gf *pa = &a[row * k];
+ gf *pb = &b[col];
+ gf acc = 0;
+ for (i = 0; i < k; i++, pa++, pb += m) acc ^= gf_mul(*pa, *pb);
+ c[row * m + col] = acc;
+ }
+ }
+}
+
+#ifdef DEBUGG
+/*
+ * returns 1 if the square matrix is identiy
+ * (only for test)
+ */
+static int is_identity(gf *m, int k) {
+ int row, col;
+ for (row = 0; row < k; row++)
+ for (col = 0; col < k; col++)
+ if ((row == col && *m != 1) || (row != col && *m != 0))
+ return 0;
+ else
+ m++;
+ return 1;
+}
+#endif /* debug */
+
+/*
+ * invert_mat() takes a matrix and produces its inverse
+ * k is the size of the matrix.
+ * (Gauss-Jordan, adapted from Numerical Recipes in C)
+ * Return non-zero if singular.
+ */
+DEB(int pivloops = 0; int pivswaps = 0; /* diagnostic */)
+static int invert_mat(gf *src, int k) {
+ gf c, *p;
+ int irow, icol, row, col, i, ix;
+
+ int error = 1;
+ int *indxc = (int *)my_malloc(k * sizeof(int), "indxc");
+ int *indxr = (int *)my_malloc(k * sizeof(int), "indxr");
+ int *ipiv = (int *)my_malloc(k * sizeof(int), "ipiv");
+ gf *id_row = NEW_GF_MATRIX(1, k);
+ gf *temp_row = NEW_GF_MATRIX(1, k);
+
+ bzero(id_row, k * sizeof(gf));
+ DEB(pivloops = 0; pivswaps = 0; /* diagnostic */)
+ /*
+ * ipiv marks elements already used as pivots.
+ */
+ for (i = 0; i < k; i++) ipiv[i] = 0;
+
+ for (col = 0; col < k; col++) {
+ gf *pivot_row;
+ /*
+ * Zeroing column 'col', look for a non-zero element.
+ * First try on the diagonal, if it fails, look elsewhere.
+ */
+ irow = icol = -1;
+ if (ipiv[col] != 1 && src[col * k + col] != 0) {
+ irow = col;
+ icol = col;
+ goto found_piv;
+ }
+ for (row = 0; row < k; row++) {
+ if (ipiv[row] != 1) {
+ for (ix = 0; ix < k; ix++) {
+ DEB(pivloops++;)
+ if (ipiv[ix] == 0) {
+ if (src[row * k + ix] != 0) {
+ irow = row;
+ icol = ix;
+ goto found_piv;
+ }
+ } else if (ipiv[ix] > 1) {
+ fprintf(stderr, "singular matrix\n");
+ goto fail;
+ }
+ }
+ }
+ }
+ if (icol == -1) {
+ fprintf(stderr, "XXX pivot not found!\n");
+ goto fail;
+ }
+ found_piv:
+ ++(ipiv[icol]);
+ /*
+ * swap rows irow and icol, so afterwards the diagonal
+ * element will be correct. Rarely done, not worth
+ * optimizing.
+ */
+ if (irow != icol) {
+ for (ix = 0; ix < k; ix++) {
+ SWAP(src[irow * k + ix], src[icol * k + ix], gf);
+ }
+ }
+ indxr[col] = irow;
+ indxc[col] = icol;
+ pivot_row = &src[icol * k];
+ c = pivot_row[icol];
+ if (c == 0) {
+ fprintf(stderr, "singular matrix 2\n");
+ goto fail;
+ }
+ if (c != 1) { /* otherwhise this is a NOP */
+ /*
+ * this is done often , but optimizing is not so
+ * fruitful, at least in the obvious ways (unrolling)
+ */
+ DEB(pivswaps++;)
+ c = inverse[c];
+ pivot_row[icol] = 1;
+ for (ix = 0; ix < k; ix++) pivot_row[ix] = gf_mul(c, pivot_row[ix]);
+ }
+ /*
+ * from all rows, remove multiples of the selected row
+ * to zero the relevant entry (in fact, the entry is not zero
+ * because we know it must be zero).
+ * (Here, if we know that the pivot_row is the identity,
+ * we can optimize the addmul).
+ */
+ id_row[icol] = 1;
+ if (bcmp(pivot_row, id_row, k * sizeof(gf)) != 0) {
+ for (p = src, ix = 0; ix < k; ix++, p += k) {
+ if (ix != icol) {
+ c = p[icol];
+ p[icol] = 0;
+ addmul(p, pivot_row, c, k);
+ }
+ }
+ }
+ id_row[icol] = 0;
+ } /* done all columns */
+ for (col = k - 1; col >= 0; col--) {
+ if (indxr[col] < 0 || indxr[col] >= k)
+ fprintf(stderr, "AARGH, indxr[col] %d\n", indxr[col]);
+ else if (indxc[col] < 0 || indxc[col] >= k)
+ fprintf(stderr, "AARGH, indxc[col] %d\n", indxc[col]);
+ else if (indxr[col] != indxc[col]) {
+ for (row = 0; row < k; row++) {
+ SWAP(src[row * k + indxr[col]], src[row * k + indxc[col]], gf);
+ }
+ }
+ }
+ error = 0;
+fail:
+ free(indxc);
+ free(indxr);
+ free(ipiv);
+ free(id_row);
+ free(temp_row);
+ return error;
+}
+
+/*
+ * fast code for inverting a vandermonde matrix.
+ * XXX NOTE: It assumes that the matrix
+ * is not singular and _IS_ a vandermonde matrix. Only uses
+ * the second column of the matrix, containing the p_i's.
+ *
+ * Algorithm borrowed from "Numerical recipes in C" -- sec.2.8, but
+ * largely revised for my purposes.
+ * p = coefficients of the matrix (p_i)
+ * q = values of the polynomial (known)
+ */
+
+int invert_vdm(gf *src, int k) {
+ int i, j, row, col;
+ gf *b, *c, *p;
+ gf t, xx;
+
+ if (k == 1) /* degenerate case, matrix must be p^0 = 1 */
+ return 0;
+ /*
+ * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1
+ * b holds the coefficient for the matrix inversion
+ */
+ c = NEW_GF_MATRIX(1, k);
+ b = NEW_GF_MATRIX(1, k);
+
+ p = NEW_GF_MATRIX(1, k);
+
+ for (j = 1, i = 0; i < k; i++, j += k) {
+ c[i] = 0;
+ p[i] = src[j]; /* p[i] */
+ }
+ /*
+ * construct coeffs. recursively. We know c[k] = 1 (implicit)
+ * and start P_0 = x - p_0, then at each stage multiply by
+ * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1}
+ * After k steps we are done.
+ */
+ c[k - 1] = p[0]; /* really -p(0), but x = -x in GF(2^m) */
+ for (i = 1; i < k; i++) {
+ gf p_i = p[i]; /* see above comment */
+ for (j = k - 1 - (i - 1); j < k - 1; j++) c[j] ^= gf_mul(p_i, c[j + 1]);
+ c[k - 1] ^= p_i;
+ }
+
+ for (row = 0; row < k; row++) {
+ /*
+ * synthetic division etc.
+ */
+ xx = p[row];
+ t = 1;
+ b[k - 1] = 1; /* this is in fact c[k] */
+ for (i = k - 2; i >= 0; i--) {
+ b[i] = c[i + 1] ^ gf_mul(xx, b[i + 1]);
+ t = gf_mul(xx, t) ^ b[i];
+ }
+ for (col = 0; col < k; col++)
+ src[col * k + row] = gf_mul(inverse[t], b[col]);
+ }
+ free(c);
+ free(b);
+ free(p);
+ return 0;
+}
+
+static int fec_initialized = 0;
+static void init_fec() {
+ TICK(ticks[0]);
+ generate_gf();
+ TOCK(ticks[0]);
+ DDB(fprintf(stderr, "generate_gf took %ldus\n", ticks[0]);)
+ TICK(ticks[0]);
+ init_mul_table();
+ TOCK(ticks[0]);
+ DDB(fprintf(stderr, "init_mul_table took %ldus\n", ticks[0]);)
+ fec_initialized = 1;
+}
+
+/*
+ * This section contains the proper FEC encoding/decoding routines.
+ * The encoding matrix is computed starting with a Vandermonde matrix,
+ * and then transforming it into a systematic matrix.
+ */
+
+#define FEC_MAGIC 0xFECC0DEC
+
+void fec_free(struct fec_parms *p) {
+ if (p == NULL || p->magic != (((FEC_MAGIC ^ p->k) ^ p->n) ^
+ (unsigned long)(p->enc_matrix))) {
+ fprintf(stderr, "bad parameters to fec_free\n");
+ return;
+ }
+ free(p->enc_matrix);
+ free(p);
+}
+
+/*
+ * create a new encoder, returning a descriptor. This contains k,n and
+ * the encoding matrix.
+ */
+struct fec_parms *fec_new(int k, int n) {
+ int row, col;
+ gf *p, *tmp_m;
+
+ struct fec_parms *retval;
+
+ if (fec_initialized == 0) init_fec();
+
+ if (k > GF_SIZE + 1 || n > GF_SIZE + 1 || k > n) {
+ fprintf(stderr, "Invalid parameters k %d n %d GF_SIZE %d\n", k, n, GF_SIZE);
+ return NULL;
+ }
+ retval = (struct fec_parms *)my_malloc(sizeof(struct fec_parms), "new_code");
+ retval->k = k;
+ retval->n = n;
+ retval->enc_matrix = NEW_GF_MATRIX(n, k);
+ retval->magic = ((FEC_MAGIC ^ k) ^ n) ^ (unsigned long)(retval->enc_matrix);
+ tmp_m = NEW_GF_MATRIX(n, k);
+ /*
+ * fill the matrix with powers of field elements, starting from 0.
+ * The first row is special, cannot be computed with exp. table.
+ */
+ tmp_m[0] = 1;
+ for (col = 1; col < k; col++) tmp_m[col] = 0;
+ for (p = tmp_m + k, row = 0; row < n - 1; row++, p += k) {
+ for (col = 0; col < k; col++) p[col] = gf_exp[modnn(row * col)];
+ }
+
+ /*
+ * quick code to build systematic matrix: invert the top
+ * k*k vandermonde matrix, multiply right the bottom n-k rows
+ * by the inverse, and construct the identity matrix at the top.
+ */
+ TICK(ticks[3]);
+ invert_vdm(tmp_m, k); /* much faster than invert_mat */
+ matmul(tmp_m + k * k, tmp_m, retval->enc_matrix + k * k, n - k, k, k);
+ /*
+ * the upper matrix is I so do not bother with a slow multiply
+ */
+ bzero(retval->enc_matrix, k * k * sizeof(gf));
+ for (p = retval->enc_matrix, col = 0; col < k; col++, p += k + 1) *p = 1;
+ free(tmp_m);
+ TOCK(ticks[3]);
+
+ DDB(fprintf(stderr, "--- %ld us to build encoding matrix\n", ticks[3]);)
+ DEB(pr_matrix(retval->enc_matrix, n, k, "encoding_matrix");)
+ return retval;
+}
+
+/*
+ * fec_encode accepts as input pointers to n data packets of size sz,
+ * and produces as output a packet pointed to by fec, computed
+ * with index "index".
+ */
+void fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz) {
+ int i, k = code->k;
+ gf *p;
+
+ if (GF_BITS > 8) sz /= 2;
+
+ if (index < k)
+ bcopy(src[index], fec, sz * sizeof(gf));
+ else if (index < code->n) {
+ p = &(code->enc_matrix[index * k]);
+ bzero(fec, sz * sizeof(gf));
+ for (i = 0; i < k; i++) addmul(fec, src[i], p[i], sz);
+ } else
+ fprintf(stderr, "Invalid index %d (max %d)\n", index, code->n - 1);
+}
+
+/*
+ * shuffle move src packets in their position
+ */
+static int shuffle(gf *pkt[], int index[], int k) {
+ int i;
+
+ for (i = 0; i < k;) {
+ if (index[i] >= k || index[i] == i)
+ i++;
+ else {
+ /*
+ * put pkt in the right position (first check for conflicts).
+ */
+ int c = index[i];
+
+ if (index[c] == c) {
+ DEB(fprintf(stderr, "\nshuffle, error at %d\n", i);)
+ return 1;
+ }
+ SWAP(index[i], index[c], int);
+ SWAP(pkt[i], pkt[c], gf *);
+ }
+ }
+ DEB(/* just test that it works... */
+ for (i = 0; i < k; i++) {
+ if (index[i] < k && index[i] != i) {
+ fprintf(stderr, "shuffle: after\n");
+ for (i = 0; i < k; i++) fprintf(stderr, "%3d ", index[i]);
+ fprintf(stderr, "\n");
+ return 1;
+ }
+ })
+ return 0;
+}
+
+/*
+ * build_decode_matrix constructs the encoding matrix given the
+ * indexes. The matrix must be already allocated as
+ * a vector of k*k elements, in row-major order
+ */
+static gf *build_decode_matrix(struct fec_parms *code, gf *pkt[], int index[]) {
+ int i, k = code->k;
+ gf *p, *matrix = NEW_GF_MATRIX(k, k);
+
+ TICK(ticks[9]);
+ for (i = 0, p = matrix; i < k; i++, p += k) {
+#if 1 /* this is simply an optimization, not very useful indeed */
+ if (index[i] < k) {
+ bzero(p, k * sizeof(gf));
+ p[i] = 1;
+ } else
+#endif
+ if (index[i] < code->n)
+ bcopy(&(code->enc_matrix[index[i] * k]), p, k * sizeof(gf));
+ else {
+ fprintf(stderr, "decode: invalid index %d (max %d)\n", index[i],
+ code->n - 1);
+ free(matrix);
+ return NULL;
+ }
+ }
+ TICK(ticks[9]);
+ if (invert_mat(matrix, k)) {
+ free(matrix);
+ matrix = NULL;
+ }
+ TOCK(ticks[9]);
+ return matrix;
+}
+
+/*
+ * fec_decode receives as input a vector of packets, the indexes of
+ * packets, and produces the correct vector as output.
+ *
+ * Input:
+ * code: pointer to code descriptor
+ * pkt: pointers to received packets. They are modified
+ * to store the output packets (in place)
+ * index: pointer to packet indexes (modified)
+ * sz: size of each packet
+ */
+int fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz) {
+ gf *m_dec;
+ gf **new_pkt;
+ int row, col, k = code->k;
+
+ if (GF_BITS > 8) sz /= 2;
+
+ if (shuffle(pkt, index, k)) /* error if true */
+ return 1;
+ m_dec = build_decode_matrix(code, pkt, index);
+
+ if (m_dec == NULL) return 1; /* error */
+ /*
+ * do the actual decoding
+ */
+ new_pkt = (gf **)my_malloc(k * sizeof(gf *), "new pkt pointers");
+ for (row = 0; row < k; row++) {
+ if (index[row] >= k) {
+ new_pkt[row] = (gf *)my_malloc(sz * sizeof(gf), "new pkt buffer");
+ bzero(new_pkt[row], sz * sizeof(gf));
+ for (col = 0; col < k; col++)
+ addmul(new_pkt[row], pkt[col], m_dec[row * k + col], sz);
+ }
+ }
+ /*
+ * move pkts to their final destination
+ */
+ for (row = 0; row < k; row++) {
+ if (index[row] >= k) {
+ bcopy(new_pkt[row], pkt[row], sz * sizeof(gf));
+ free(new_pkt[row]);
+ }
+ }
+ free(new_pkt);
+ free(m_dec);
+
+ return 0;
+}
diff --git a/libtransport/src/core/fec.h b/libtransport/src/protocols/fec/fec.h
index 8234057a7..7710bb7af 100644
--- a/libtransport/src/core/fec.h
+++ b/libtransport/src/protocols/fec/fec.h
@@ -39,7 +39,7 @@
* This is the only parameter you may want to change.
*/
#ifndef GF_BITS
-#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */
+#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */
#endif
#if (GF_BITS <= 8)
@@ -48,16 +48,16 @@ typedef unsigned char gf;
typedef unsigned short gf;
#endif
-#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */
+#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */
struct fec_parms {
- unsigned long magic ;
- int k, n ; /* parameters of the code */
- gf *enc_matrix ;
+ unsigned long magic;
+ int k, n; /* parameters of the code */
+ gf *enc_matrix;
};
-void fec_free(struct fec_parms *p) ;
-struct fec_parms *fec_new(int k, int n) ;
+void fec_free(struct fec_parms *p);
+struct fec_parms *fec_new(int k, int n);
void fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz);
int fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz);
diff --git a/libtransport/src/protocols/fec/fec_info.h b/libtransport/src/protocols/fec/fec_info.h
new file mode 100644
index 000000000..bdfc4d3af
--- /dev/null
+++ b/libtransport/src/protocols/fec/fec_info.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/errors/not_implemented_exception.h>
+
+namespace transport {
+namespace protocol {
+
+namespace fec {
+
+template <typename T>
+struct FecInfo {
+ static bool isFec() { throw errors::NotImplementedException(); }
+ static uint32_t nextSymbol(uint32_t index) {
+ throw errors::NotImplementedException();
+ }
+ static uint32_t nextSource(uint32_t index) {
+ throw errors::NotImplementedException();
+ }
+};
+
+template <uint32_t K, uint32_t N>
+struct Code {};
+
+template <uint32_t K, uint32_t N>
+struct FecInfo<Code<K, N>> {
+ static bool isFec(uint32_t index) { return (index % N) >= K; }
+
+ static uint32_t nextSymbol(uint32_t index) {
+ if (isFec(index)) {
+ return index;
+ }
+
+ return index + (K - (index % N));
+ }
+
+ static uint32_t nextSource(uint32_t index) {
+ if (!isFec(index)) {
+ return index;
+ }
+
+ return index + (N - (index % N));
+ }
+};
+
+} // namespace fec
+} // namespace protocol
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/fec/rely.cc b/libtransport/src/protocols/fec/rely.cc
new file mode 100644
index 000000000..7a30a62e2
--- /dev/null
+++ b/libtransport/src/protocols/fec/rely.cc
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glog/logging.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <protocols/fec/rely.h>
+
+#include <rely/packet.hpp>
+
+namespace transport {
+namespace protocol {
+namespace fec {
+
+RelyEncoder::RelyEncoder(uint32_t k, uint32_t n, uint32_t seq_offset)
+ : RelyBase(k, n) {
+ configure(kmtu, ktimeout, kmax_stream_size);
+ set_repair_trigger(k_, n_ - k_, n_ - k_);
+}
+
+void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
+ uint32_t offset) {
+ // Get pointer to payload, leaving space to insert FEC header.
+ // TODO Check if this additional header is really needed.
+ auto data = content_object.writableData() + offset - sizeof(fec_header);
+ auto length = content_object.length() - offset + sizeof(fec_header);
+
+ // Check packet length does not exceed maximum length supported by the
+ // encoder (otherwise segmentation would take place).
+ assert(length < max_packet_bytes());
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Encoding packet of length " << length - sizeof(fec_header);
+
+ // Get the suffix. With rely we need to write it in the fec_header in order to
+ // be able to recognize the seq number upon recovery.
+ auto suffix = content_object.getName().getSuffix();
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Producing packet " << suffix
+ << " (index == " << current_index_ << ")";
+
+ // Consume payload. Add fec_header in front before feeding payload to encoder,
+ // and copy original content of packet
+ fec_header *h = reinterpret_cast<fec_header *>(data);
+ fec_header copy = *h;
+ h->setSeqNumberBase(suffix);
+ auto packets = consume(data, length, getCurrentTime());
+ assert(packets == 1);
+
+ // Update packet counter
+ current_index_ += packets;
+
+ // Restore original packet content and increment data pointer to the correct
+ // position
+ *h = copy;
+ data += sizeof(fec_header);
+
+ // Check position of this packet inside N size block
+ auto i = current_index_ % n_;
+
+ // encoder will produce a source packet
+ if (i <= k_) {
+ // Rely modifies the payload of the packet. We replace the packet with the
+ // one returned by rely.
+ // TODO Optimize it by copying only the RELY header
+
+ // Be sure encoder can produce
+ assert(can_produce());
+
+ // Check new payload size and make sure it fits in packet buffer
+ auto new_payload_size = produce_bytes();
+ int difference = new_payload_size - length;
+
+ assert(difference > 0);
+ assert(content_object.ensureCapacity(difference));
+
+ // Update length
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "The packet length will be incremented by "
+ << difference + sizeof(fec_header);
+ content_object.append(difference + sizeof(fec_header));
+ content_object.updateLength();
+
+ // Make sure we got a source packet, otherwise we would put a repair symbol
+ // in a source packet
+ assert(rely::packet_is_systematic(produce_data()));
+
+ // Copy rely packet replacing old source packet.
+ std::memcpy(data, produce_data(), new_payload_size);
+
+ // Advance the encoder to next symbol.
+ produce_next();
+ }
+
+#if 0
+ if (i == k_) {
+ // Ensure repair are generated after k source packets
+ flush_repair();
+ }
+#endif
+
+ // Here we should produce all the repair packets
+ while (can_produce()) {
+ // The current index MUST be k_, because we enforce n - k repair to be
+ // produced after k sources
+ assert(current_index_ == k_);
+
+ buffer packet;
+ if (!buffer_callback_) {
+ // If no callback is installed, let's allocate a buffer from global pool
+ packet = core::PacketManager<>::getInstance().getMemBuf();
+ packet->append(produce_bytes());
+ } else {
+ // Otherwise let's ask a buffer to the caller.
+ packet = buffer_callback_(produce_bytes());
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Producing symbol of size " << produce_bytes();
+
+ // Copy symbol to packet buffer
+ std::memcpy(packet->writableData(), produce_data(), produce_bytes());
+
+ // Push symbol in repair_packets
+ packets_.emplace_back(0, std::move(packet));
+
+ // Advance the encoder
+ produce_next();
+ }
+
+ // Print number of unprotected symbols
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Number of unprotected symbols: " << unprotected_symbols();
+
+ // If we have generated repair symbols, let's notify caller via the installed
+ // callback
+ if (packets_.size()) {
+ assert(packets_.size() == n_ - k_);
+ fec_callback_(packets_);
+ packets_.clear();
+ current_index_ = 0;
+ }
+}
+
+RelyDecoder::RelyDecoder(uint32_t k, uint32_t n, uint32_t seq_offset)
+ : RelyBase(k, n, seq_offset) {
+ configure(kmtu, ktimeout, kmax_stream_size);
+}
+
+void RelyDecoder::onDataPacket(core::ContentObject &content_object,
+ uint32_t offset) {
+ // Adjust pointers to point to packet payload
+ auto data = content_object.writableData() + offset;
+ auto size = content_object.length() - offset;
+
+ // Pass payload to decoder
+ consume(data, size, getCurrentTime());
+
+ // Drain decoder if possible
+ while (can_produce()) {
+ // Get size of decoded packet
+ auto size = produce_bytes();
+
+ // Get buffer to copy packet in
+ auto packet = core::PacketManager<>::getInstance().getMemBuf();
+
+ // Copy buffer
+ packet->append(size);
+ std::memcpy(packet->writableData(), produce_data(), size);
+
+ // Read seq number
+ fec_header *h = reinterpret_cast<fec_header *>(packet->writableData());
+ uint32_t index = h->getSeqNumberBase();
+
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "The index written in the packet is " << index;
+
+ // Remove FEC header
+ packet->trimStart(sizeof(fec_header));
+
+ // Save packet in buffer
+ packets_.emplace_back(index, std::move(packet));
+
+ // Advance to next packet
+ produce_next();
+ }
+
+ // If we produced packets, lets notify the caller via the callback
+ if (packets_.size() > 0) {
+ fec_callback_(packets_);
+ packets_.clear();
+ }
+}
+
+} // namespace fec
+} // namespace protocol
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/fec/rely.h b/libtransport/src/protocols/fec/rely.h
new file mode 100644
index 000000000..bfbdb30bc
--- /dev/null
+++ b/libtransport/src/protocols/fec/rely.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/utils/chrono_typedefs.h>
+#include <hicn/transport/utils/membuf.h>
+#include <protocols/fec/fec_info.h>
+#include <protocols/fec_base.h>
+
+#include <rely/decoder.hpp>
+#include <rely/encoder.hpp>
+
+#define RELY_DEBUG 0
+
+namespace transport {
+namespace protocol {
+namespace fec {
+
+/**
+ * @brief Table of used codes.
+ */
+#define foreach_rely_fec_type \
+ _(Rely, 1, 3) \
+ _(Rely, 2, 3) \
+ _(Rely, 4, 5) \
+ _(Rely, 4, 6) \
+ _(Rely, 4, 7) \
+ _(Rely, 6, 10) \
+ _(Rely, 8, 10) \
+ _(Rely, 8, 11) \
+ _(Rely, 8, 12) \
+ _(Rely, 8, 14) \
+ _(Rely, 8, 16) \
+ _(Rely, 8, 32) \
+ _(Rely, 10, 30) \
+ _(Rely, 10, 40) \
+ _(Rely, 10, 90) \
+ _(Rely, 16, 21) \
+ _(Rely, 16, 23) \
+ _(Rely, 16, 24) \
+ _(Rely, 16, 27) \
+ _(Rely, 17, 21) \
+ _(Rely, 17, 34) \
+ _(Rely, 32, 41) \
+ _(Rely, 32, 46) \
+ _(Rely, 32, 54) \
+ _(Rely, 34, 42) \
+ _(Rely, 35, 70) \
+ _(Rely, 52, 62)
+
+/**
+ * @brief Base class to store common fields.
+ */
+class RelyBase : public virtual FECBase {
+ protected:
+ static const constexpr size_t kmax_stream_size = 125U;
+ static const constexpr size_t kmtu = 1500U;
+ static const constexpr size_t ktimeout = 100U;
+ /**
+ * @brief FEC Header, added to each packet to get sequence number upon
+ * decoding operations. It may be removed once we know the meaning of the
+ * fields in the rely header.
+ */
+ struct fec_header {
+ uint32_t seq_number;
+
+ void setSeqNumberBase(uint32_t suffix) { seq_number = htonl(suffix); }
+ uint32_t getSeqNumberBase() { return ntohl(seq_number); }
+ };
+
+ /**
+ * @brief Construct a new Rely Base object.
+ *
+ * @param k The number of source symbol needed to generate n - k repair
+ * symbols
+ * @param n The sum of source packets and repair packets in a `block`
+ * @param seq_offset offset to use if production suffixes starts from an index
+ * != 0
+ */
+ RelyBase(uint32_t k, uint32_t n, uint32_t seq_offset = 0)
+ : k_(k),
+ n_(n),
+ seq_offset_(seq_offset % n_),
+ current_index_(seq_offset)
+#if RELY_DEBUG
+ ,
+ time_(0)
+#endif
+ {
+ }
+
+ /**
+ * @brief Get the current time in milliseconds
+ *
+ * @return int64_t Current time in milliseconds
+ */
+ int64_t getCurrentTime() {
+ // Get the current time
+#if RELY_DEBUG
+ return time_++;
+#else
+ auto _time = utils::SteadyClock::now().time_since_epoch();
+ auto time = std::chrono::duration_cast<utils::Milliseconds>(_time).count();
+ return time;
+#endif
+ }
+
+ protected:
+ uint32_t k_;
+ uint32_t n_;
+ std::uint32_t seq_offset_;
+ /**
+ * @brief Vector of packets to be passed to caller callbacks. For encoder it
+ * will contain the repair packets, for decoder the recovered sources.
+ */
+ std::vector<std::pair<uint32_t, buffer>> packets_;
+
+ /**
+ * @brief Current index to be used for local packet count.
+ *
+ */
+ uint32_t current_index_;
+#if RELY_DEBUG
+ uint32_t time_;
+#endif
+};
+
+/**
+ * @brief The Rely Encoder implementation.
+ *
+ */
+class RelyEncoder : private RelyBase,
+ private rely::encoder,
+ public ProducerFEC {
+ public:
+ RelyEncoder(uint32_t k, uint32_t n, uint32_t seq_offset = 0);
+ /**
+ * Producers will call this function when they produce a data packet.
+ */
+ void onPacketProduced(core::ContentObject &content_object,
+ uint32_t offset) override;
+
+ /**
+ * @brief Get the fec header size, if added to source packets
+ */
+ std::size_t getFecHeaderSize() override {
+ return header_bytes() + sizeof(fec_header) + 4;
+ }
+
+ void reset() override {}
+};
+
+class RelyDecoder : private RelyBase,
+ private rely::decoder,
+ public ConsumerFEC {
+ public:
+ RelyDecoder(uint32_t k, uint32_t n, uint32_t seq_offset = 0);
+
+ /**
+ * Consumers will call this function when they receive a data packet
+ */
+ void onDataPacket(core::ContentObject &content_object,
+ uint32_t offset) override;
+
+ /**
+ * @brief Get the fec header size, if added to source packets
+ */
+ std::size_t getFecHeaderSize() override {
+ return header_bytes() + sizeof(fec_header);
+ }
+
+ void reset() override {}
+};
+
+} // namespace fec
+
+} // namespace protocol
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/fec/rs.cc b/libtransport/src/protocols/fec/rs.cc
new file mode 100644
index 000000000..2c23d515d
--- /dev/null
+++ b/libtransport/src/protocols/fec/rs.cc
@@ -0,0 +1,418 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glog/logging.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <protocols/fec/fec.h>
+#include <protocols/fec/rs.h>
+
+#include <cassert>
+
+namespace transport {
+namespace protocol {
+namespace fec {
+
+BlockCode::BlockCode(uint32_t k, uint32_t n, uint32_t seq_offset,
+ struct fec_parms *code, rs &params)
+ : Packets(),
+ k_(k),
+ n_(n),
+ seq_offset_(seq_offset),
+ code_(code),
+ max_buffer_size_(0),
+ current_block_size_(0),
+ to_decode_(false),
+ params_(params) {
+ sorted_index_.reserve(n);
+ UNUSED(seq_offset_);
+}
+
+bool BlockCode::addRepairSymbol(const fec::buffer &packet, uint32_t i,
+ uint32_t offset) {
+ // Get index
+ to_decode_ = true;
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Adding symbol of size " << packet->length();
+ return addSymbol(packet, i, offset,
+ packet->length() - sizeof(fec_header) - offset);
+}
+
+bool BlockCode::addSourceSymbol(const fec::buffer &packet, uint32_t i,
+ uint32_t offset) {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Adding source symbol of size "
+ << packet->length() << ", offset " << offset;
+ return addSymbol(packet, i, offset, packet->length() - offset);
+}
+
+bool BlockCode::addSymbol(const fec::buffer &packet, uint32_t i,
+ uint32_t offset, std::size_t size) {
+ if (size > max_buffer_size_) {
+ max_buffer_size_ = size;
+ }
+
+ operator[](current_block_size_++) = std::make_tuple(i, packet, offset);
+
+ if (current_block_size_ >= k_) {
+ if (to_decode_) {
+ decode();
+ } else {
+ encode();
+ }
+
+ clear();
+ return false;
+ }
+
+ return true;
+}
+
+void BlockCode::encode() {
+ gf *data[n_];
+ uint32_t base = std::get<0>(operator[](0));
+
+ // Set packet length in first 2 bytes
+ for (uint32_t i = 0; i < k_; i++) {
+ auto &packet = std::get<1>(operator[](i));
+ auto offset = std::get<2>(operator[](i));
+
+ auto ret =
+ packet->ensureCapacityAndFillUnused(max_buffer_size_ + offset, 0);
+ if (TRANSPORT_EXPECT_FALSE(ret == false)) {
+ throw errors::RuntimeException(
+ "Provided packet is not suitable to be used as FEC source packet. "
+ "Aborting.");
+ }
+
+ // Buffers should hold 2 *after* the padding, in order to be
+ // able to set the length for the encoding operation.
+ // packet->trimStart(offset);
+ uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData() +
+ max_buffer_size_ + offset);
+ auto buffer_length = packet->length() - offset;
+ *length = htons(buffer_length);
+
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Current buffer size: " << packet->length();
+
+ data[i] = packet->writableData() + offset;
+ }
+
+ // Finish to fill source block with the buffers to hold the repair symbols
+ auto length = max_buffer_size_ + sizeof(fec_header) + LEN_SIZE_BYTES;
+ for (uint32_t i = k_; i < n_; i++) {
+ buffer packet;
+ if (!params_.buffer_callback_) {
+ // If no callback is installed, let's allocate a buffer from global pool
+ packet = core::PacketManager<>::getInstance().getMemBuf();
+ packet->append(length);
+ } else {
+ // Otherwise let's ask a buffer to the caller.
+ packet = params_.buffer_callback_(length);
+ }
+
+ fec_header *fh = reinterpret_cast<fec_header *>(packet->writableData());
+
+ fh->setSeqNumberBase(base);
+ fh->setNFecSymbols(n_ - k_);
+ fh->setEncodedSymbolId(i);
+ fh->setSourceBlockLen(n_);
+
+ packet->trimStart(sizeof(fec_header));
+
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Current symbol size: " << packet->length();
+
+ data[i] = packet->writableData();
+ operator[](i) = std::make_tuple(i, std::move(packet), uint32_t(0));
+ }
+
+ // Generate repair symbols and put them in corresponding buffers
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Calling encode with max_buffer_size_ = " << max_buffer_size_;
+ for (uint32_t i = k_; i < n_; i++) {
+ fec_encode(code_, data, data[i], i, max_buffer_size_ + LEN_SIZE_BYTES);
+ }
+
+ // Re-include header in repair packets
+ for (uint32_t i = k_; i < n_; i++) {
+ auto &packet = std::get<1>(operator[](i));
+ packet->prepend(sizeof(fec_header));
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Produced repair symbol of size = " << packet->length();
+ }
+}
+
+void BlockCode::decode() {
+ gf *data[k_];
+ uint32_t index[k_];
+
+ for (uint32_t i = 0; i < k_; i++) {
+ auto &packet = std::get<1>(operator[](i));
+ index[i] = std::get<0>(operator[](i));
+ auto offset = std::get<2>(operator[](i));
+ sorted_index_[i] = index[i];
+
+ if (index[i] < k_) {
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "DECODE SOURCE - index " << index[i]
+ << " - Current buffer size: " << packet->length();
+ // This is a source packet. We need to fill
+ // additional space to 0 and append the length
+
+ // Buffers should hold 2 bytes at the end, in order to be
+ // able to set the length for the encoding operation
+ packet->trimStart(offset);
+ packet->ensureCapacityAndFillUnused(max_buffer_size_, 0);
+ uint16_t *length = reinterpret_cast<uint16_t *>(
+ packet->writableData() + max_buffer_size_ - LEN_SIZE_BYTES);
+
+ *length = htons(packet->length());
+ } else {
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "DECODE SYMBOL - index " << index[i]
+ << " - Current buffer size: " << packet->length();
+ packet->trimStart(sizeof(fec_header) + offset);
+ }
+
+ data[i] = packet->writableData();
+ }
+
+ // We decode the source block
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Calling decode with max_buffer_size_ = " << max_buffer_size_;
+ fec_decode(code_, data, reinterpret_cast<int *>(index), max_buffer_size_);
+
+ // Find the index in the block for recovered packets
+ for (uint32_t i = 0; i < k_; i++) {
+ if (index[i] != i) {
+ for (uint32_t j = 0; j < k_; j++)
+ if (sorted_index_[j] == uint32_t(index[i])) {
+ sorted_index_[j] = i;
+ }
+ }
+ }
+
+ // Reorder block by index with in-place sorting
+ for (uint32_t i = 0; i < k_; i++) {
+ for (uint32_t j = sorted_index_[i]; j != i; j = sorted_index_[i]) {
+ std::swap(sorted_index_[j], sorted_index_[i]);
+ std::swap(operator[](j), operator[](i));
+ }
+ }
+
+ // Adjust length according to the one written in the source packet
+ for (uint32_t i = 0; i < k_; i++) {
+ auto &packet = std::get<1>(operator[](i));
+ uint16_t *length = reinterpret_cast<uint16_t *>(
+ packet->writableData() + max_buffer_size_ - LEN_SIZE_BYTES);
+ packet->setLength(ntohs(*length));
+ }
+}
+
+void BlockCode::clear() {
+ current_block_size_ = 0;
+ max_buffer_size_ = 0;
+ sorted_index_.clear();
+ to_decode_ = false;
+}
+
+void rs::MatrixDeleter::operator()(struct fec_parms *params) {
+ fec_free(params);
+}
+
+rs::Codes rs::createCodes() {
+ Codes ret;
+
+#define _(name, k, n) \
+ ret.emplace(std::make_pair(k, n), Matrix(fec_new(k, n), MatrixDeleter()));
+ foreach_rs_fec_type
+#undef _
+
+ return ret;
+}
+
+rs::Codes rs::codes_ = createCodes();
+
+rs::rs(uint32_t k, uint32_t n, uint32_t seq_offset)
+ : k_(k), n_(n), seq_offset_(seq_offset % n) {}
+
+RSEncoder::RSEncoder(uint32_t k, uint32_t n, uint32_t seq_offset)
+ : rs(k, n, seq_offset),
+ current_code_(codes_[std::make_pair(k, n)].get()),
+ source_block_(k_, n_, seq_offset_, current_code_, *this) {}
+
+void RSEncoder::consume(const fec::buffer &packet, uint32_t index,
+ uint32_t offset) {
+ if (!source_block_.addSourceSymbol(packet, index, offset)) {
+ std::vector<std::pair<uint32_t, buffer>> repair_packets;
+ for (uint32_t i = k_; i < n_; i++) {
+ repair_packets.emplace_back(std::move(std::get<0>(source_block_[i])),
+ std::move(std::get<1>(source_block_[i])));
+ }
+
+ fec_callback_(repair_packets);
+ }
+}
+
+void RSEncoder::onPacketProduced(core::ContentObject &content_object,
+ uint32_t offset) {
+ consume(content_object.shared_from_this(),
+ content_object.getName().getSuffix(), offset);
+}
+
+RSDecoder::RSDecoder(uint32_t k, uint32_t n, uint32_t seq_offset)
+ : rs(k, n, seq_offset) {}
+
+void RSDecoder::recoverPackets(SourceBlocks::iterator &src_block_it) {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "recoverPackets for " << k_;
+ auto &src_block = src_block_it->second;
+ std::vector<std::pair<uint32_t, buffer>> source_packets(k_);
+ for (uint32_t i = 0; i < src_block.getK(); i++) {
+ source_packets[i] = std::make_pair(src_block_it->first + i,
+ std::move(std::get<1>(src_block[i])));
+ }
+
+ setProcessed(src_block_it->first);
+
+ fec_callback_(source_packets);
+ processed_source_blocks_.emplace(src_block_it->first);
+
+ auto it = parked_packets_.find(src_block_it->first);
+ if (it != parked_packets_.end()) {
+ parked_packets_.erase(it);
+ }
+
+ src_blocks_.erase(src_block_it);
+}
+
+void RSDecoder::consumeSource(const fec::buffer &packet, uint32_t index,
+ uint32_t offset) {
+ // Normalize index
+ assert(index >= seq_offset_);
+ auto i = (index - seq_offset_) % n_;
+
+ // Get base
+ uint32_t base = index - i;
+
+ if (processed(base)) {
+ return;
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Decoder consume called for source symbol. BASE = " << base
+ << ", index = " << index << " and i = " << i;
+
+ // check if a source block already exist for this symbol. If it does not
+ // exist, we lazily park this packet until we receive a repair symbol for the
+ // same block. This is done for 2 reason:
+ // 1) If we receive all the source packets of a block, we do not need to
+ // recover anything.
+ // 2) Sender may change n and k at any moment, so we construct the source
+ // block based on the (n, k) values written in the fec header. This is
+ // actually not used right now, since we use fixed value of n and k passed
+ // at construction time, but it paves the ground for a more dynamic
+ // protocol that may come in the future.
+ auto it = src_blocks_.find(base);
+ if (it != src_blocks_.end()) {
+ auto ret = it->second.addSourceSymbol(packet, i, offset);
+ if (!ret) {
+ recoverPackets(it);
+ }
+ } else {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Adding to parked source packets";
+ auto ret = parked_packets_.emplace(
+ base, std::vector<std::pair<buffer, uint32_t>>());
+ ret.first->second.emplace_back(packet, i);
+
+ if (ret.first->second.size() >= k_) {
+ setProcessed(ret.first->first);
+ parked_packets_.erase(ret.first);
+ }
+ }
+}
+
+void RSDecoder::consumeRepair(const fec::buffer &packet, uint32_t offset) {
+ // Repair symbol! Get index and base source block.
+ fec_header *h =
+ reinterpret_cast<fec_header *>(packet->writableData() + offset);
+ auto i = h->getEncodedSymbolId();
+ auto base = h->getSeqNumberBase();
+ auto n = h->getSourceBlockLen();
+ auto k = n - h->getNFecSymbols();
+
+ if (processed(base)) {
+ return;
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Decoder consume called for repair symbol. BASE = " << base
+ << ", index = " << base + i << " and i = " << i << ". K=" << k
+ << ", N=" << n;
+
+ // check if a source block already exist for this symbol
+ auto it = src_blocks_.find(base);
+ if (it == src_blocks_.end()) {
+ // Create new source block
+ auto code_it = codes_.find(std::make_pair(k, n));
+ if (code_it == codes_.end()) {
+ LOG(ERROR) << "Code for k = " << k << " and n = " << n
+ << " does not exist.";
+ return;
+ }
+
+ auto emplace_result = src_blocks_.emplace(
+ base, BlockCode(k, n, seq_offset_, code_it->second.get(), *this));
+ it = emplace_result.first;
+
+ // Check in the parked packets and insert any packet that is part of this
+ // source block
+
+ auto it2 = parked_packets_.find(base);
+ if (it2 != parked_packets_.end()) {
+ for (auto &packet_index : it2->second) {
+ auto ret = it->second.addSourceSymbol(packet_index.first,
+ packet_index.second, offset);
+ if (!ret) {
+ recoverPackets(it);
+ // Finish to delete packets in same source block that were
+ // eventually not used
+ return;
+ }
+ }
+ }
+ }
+
+ auto ret = it->second.addRepairSymbol(packet, i, offset);
+ if (!ret) {
+ recoverPackets(it);
+ }
+}
+
+void RSDecoder::onDataPacket(core::ContentObject &content_object,
+ uint32_t offset) {
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Calling fec for data packet " << content_object.getName()
+ << ". Offset: " << offset;
+
+ auto suffix = content_object.getName().getSuffix();
+
+ if (isSymbol(suffix)) {
+ consumeRepair(content_object.shared_from_this(), offset);
+ } else {
+ consumeSource(content_object.shared_from_this(), suffix, offset);
+ }
+}
+
+} // namespace fec
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/core/rs.h b/libtransport/src/protocols/fec/rs.h
index 9a8c43e4d..e159ad9f7 100644
--- a/libtransport/src/core/rs.h
+++ b/libtransport/src/protocols/fec/rs.h
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-#ifndef _WIN32
+#pragma once
+
#include <arpa/inet.h>
-#endif
+#include <hicn/transport/portability/c_portability.h>
#include <hicn/transport/utils/membuf.h>
+#include <protocols/fec/fec_info.h>
#include <protocols/fec_base.h>
#include <array>
@@ -27,13 +29,43 @@
#include <vector>
namespace transport {
-namespace core {
+namespace protocol {
namespace fec {
+#define foreach_rs_fec_type \
+ _(RS, 1, 3) \
+ _(RS, 4, 5) \
+ _(RS, 4, 6) \
+ _(RS, 4, 7) \
+ _(RS, 6, 10) \
+ _(RS, 8, 10) \
+ _(RS, 8, 11) \
+ _(RS, 8, 12) \
+ _(RS, 8, 14) \
+ _(RS, 8, 16) \
+ _(RS, 8, 32) \
+ _(RS, 10, 30) \
+ _(RS, 10, 40) \
+ _(RS, 10, 60) \
+ _(RS, 10, 90) \
+ _(RS, 16, 18) \
+ _(RS, 16, 21) \
+ _(RS, 16, 23) \
+ _(RS, 16, 24) \
+ _(RS, 16, 27) \
+ _(RS, 17, 21) \
+ _(RS, 17, 34) \
+ _(RS, 32, 36) \
+ _(RS, 32, 41) \
+ _(RS, 32, 46) \
+ _(RS, 32, 54) \
+ _(RS, 34, 42) \
+ _(RS, 35, 70) \
+ _(RS, 52, 62)
+
static const constexpr uint16_t MAX_SOURCE_BLOCK_SIZE = 128;
-using buffer = typename utils::MemBuf::Ptr;
/**
* We use a std::array in place of std::vector to avoid to allocate a new vector
* in the heap every time we build a new source block, which would be bad if
@@ -41,7 +73,9 @@ using buffer = typename utils::MemBuf::Ptr;
* std::array allows to be constructed in place, saving the allocation at the
* price os knowing in advance its size.
*/
-using Packets = std::array<std::pair<uint32_t, buffer>, MAX_SOURCE_BLOCK_SIZE>;
+using Packets = std::array<std::tuple</* index */ uint32_t, /* buffer */ buffer,
+ uint32_t /* offset */>,
+ MAX_SOURCE_BLOCK_SIZE>;
/**
* FEC Header, prepended to symbol packets.
@@ -82,6 +116,8 @@ struct fec_header {
uint8_t getNFecSymbols() { return n_fec_symbols; }
};
+class rs;
+
/**
* This class models the source block itself.
*/
@@ -93,17 +129,20 @@ class BlockCode : public Packets {
static constexpr std::size_t LEN_SIZE_BYTES = 2;
public:
- BlockCode(uint32_t k, uint32_t n, struct fec_parms *code);
+ BlockCode(uint32_t k, uint32_t n, uint32_t seq_offset, struct fec_parms *code,
+ rs &params);
/**
* Add a repair symbol to the dource block.
*/
- bool addRepairSymbol(const fec::buffer &packet, uint32_t i);
+ bool addRepairSymbol(const fec::buffer &packet, uint32_t i,
+ uint32_t offset = 0);
/**
* Add a source symbol to the source block.
*/
- bool addSourceSymbol(const fec::buffer &packet, uint32_t i);
+ bool addSourceSymbol(const fec::buffer &packet, uint32_t i,
+ uint32_t offset = 0);
/**
* Get current length of source block.
@@ -129,7 +168,8 @@ class BlockCode : public Packets {
/**
* Add symbol to source block
**/
- bool addSymbol(const fec::buffer &packet, uint32_t i, std::size_t size);
+ bool addSymbol(const fec::buffer &packet, uint32_t i, uint32_t offset,
+ std::size_t size);
/**
* Starting from k source symbols, get the n - k repair symbols
@@ -147,11 +187,13 @@ class BlockCode : public Packets {
private:
uint32_t k_;
uint32_t n_;
+ uint32_t seq_offset_;
struct fec_parms *code_;
std::size_t max_buffer_size_;
std::size_t current_block_size_;
std::vector<uint32_t> sorted_index_;
bool to_decode_;
+ rs &params_;
};
/**
@@ -166,7 +208,9 @@ class BlockCode : public Packets {
* message later to negotiate them, so that decoder cah dynamically change them
* during the download.
*/
-class rs {
+class rs : public virtual FECBase {
+ friend class BlockCode;
+
/**
* Deleter for static preallocated reed-solomon parameters.
*/
@@ -190,7 +234,7 @@ class rs {
* Custom hash function for (k, n) pair.
*/
struct CodeHasher {
- std::size_t operator()(const transport::core::fec::rs::Code &code) const {
+ std::size_t operator()(const Code &code) const {
uint64_t ret = uint64_t(code.first) << 32 | uint64_t(code.second);
return std::hash<uint64_t>{}(ret);
}
@@ -221,16 +265,13 @@ class rs {
using Codes = std::unordered_map<Code, Matrix, CodeHasher>;
public:
- rs(uint32_t k, uint32_t n);
+ rs(uint32_t k, uint32_t n, uint32_t seq_offset = 0);
~rs() = default;
- /**
- * Set callback to call after packet encoding / decoding
- */
- void setFECCallback(const PacketsReady &callback);
-
virtual void clear() { processed_source_blocks_.clear(); }
+ bool isSymbol(uint32_t index) { return ((index - seq_offset_) % n_) >= k_; }
+
private:
/**
* Create reed-solomon codes at program startup.
@@ -243,9 +284,13 @@ class rs {
processed_source_blocks_.end();
}
+ void setProcessed(SNBase seq_base) {
+ processed_source_blocks_.emplace(seq_base);
+ }
+
std::uint32_t k_;
std::uint32_t n_;
- PacketsReady fec_callback_;
+ std::uint32_t seq_offset_;
/**
* Keep track of processed source blocks
@@ -259,19 +304,29 @@ class rs {
* The reed-solomon encoder. It is feeded with source symbols and it provide
* repair-symbols through the fec_callback_
*/
-class encoder : public rs {
+class RSEncoder : public rs, public ProducerFEC {
public:
- encoder(uint32_t k, uint32_t n);
+ RSEncoder(uint32_t k, uint32_t n, uint32_t seq_offset = 0);
/**
* Always consume source symbols.
*/
- void consume(const fec::buffer &packet, uint32_t index);
+ void consume(const fec::buffer &packet, uint32_t index, uint32_t offset = 0);
+
+ void onPacketProduced(core::ContentObject &content_object,
+ uint32_t offset) override;
+
+ /**
+ * @brief Get the fec header size, if added to source packets
+ */
+ std::size_t getFecHeaderSize() override { return 0; }
void clear() override {
rs::clear();
source_block_.clear();
}
+ void reset() override { clear(); }
+
private:
struct fec_parms *current_code_;
/**
@@ -286,19 +341,31 @@ class encoder : public rs {
* The reed-solomon encoder. It is feeded with source/repair symbols and it
* provides the original source symbols through the fec_callback_
*/
-class decoder : public rs {
+class RSDecoder : public rs, public ConsumerFEC {
public:
- decoder(uint32_t k, uint32_t n);
+ RSDecoder(uint32_t k, uint32_t n, uint32_t seq_offset = 0);
/**
* Consume source symbol
*/
- void consume(const fec::buffer &packet, uint32_t i);
+ void consumeSource(const fec::buffer &packet, uint32_t i,
+ uint32_t offset = 0);
/**
* Consume repair symbol
*/
- void consume(const fec::buffer &packet);
+ void consumeRepair(const fec::buffer &packet, uint32_t offset = 0);
+
+ /**
+ * Consumers will call this function when they receive a data packet
+ */
+ void onDataPacket(core::ContentObject &content_object,
+ uint32_t offset) override;
+
+ /**
+ * @brief Get the fec header size, if added to source packets
+ */
+ std::size_t getFecHeaderSize() override { return 0; }
/**
* Clear decoder to reuse
@@ -309,6 +376,8 @@ class decoder : public rs {
parked_packets_.clear();
}
+ void reset() override { clear(); }
+
private:
void recoverPackets(SourceBlocks::iterator &src_block_it);
@@ -335,6 +404,6 @@ class decoder : public rs {
} // namespace fec
-} // namespace core
+} // namespace protocol
} // namespace transport
diff --git a/libtransport/src/interfaces/rtc_socket_producer.cc b/libtransport/src/protocols/fec_base.cc
index 07d72db7e..9252bc473 100644
--- a/libtransport/src/interfaces/rtc_socket_producer.cc
+++ b/libtransport/src/protocols/fec_base.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -13,17 +13,12 @@
* limitations under the License.
*/
-#include <hicn/transport/interfaces/rtc_socket_producer.h>
-
-#include <implementation/rtc_socket_producer.h>
+#include <protocols/fec/rs.h>
+#include <protocols/fec_base.h>
namespace transport {
-namespace interface {
-
-RTCProducerSocket::RTCProducerSocket() : ProducerSocket(false) {
- socket_ = std::make_unique<implementation::RTCProducerSocket>(this);
-}
-
-} // namespace interface
+namespace protocol {
-} // namespace transport
+namespace fec {} // namespace fec
+} // namespace protocol
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/fec_base.h b/libtransport/src/protocols/fec_base.h
index a135c474f..a1929d85e 100644
--- a/libtransport/src/protocols/fec_base.h
+++ b/libtransport/src/protocols/fec_base.h
@@ -16,71 +16,88 @@
#pragma once
#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
#include <functional>
namespace transport {
namespace protocol {
-/**
- * Interface classes to integrate FEC inside any producer transport protocol
- */
-class ProducerFECBase {
+namespace fec {
+
+using buffer = typename utils::MemBuf::Ptr;
+using BufferArray = std::vector<std::pair<uint32_t, buffer>>;
+
+class FECBase {
public:
+ virtual ~FECBase() = default;
/**
- * Callback, to be called by implementations as soon as a repair packet is
- * ready.
+ * Callback to be called after the encode or the decode operations. In the
+ * former case it will contain the symbols, while in the latter the sources.
*/
- using RepairPacketsReady =
- std::function<void(std::vector<core::ContentObject::Ptr> &)>;
+ using PacketsReady = std::function<void(BufferArray &)>;
/**
- * Producers will call this function upon production of a new packet.
+ * Callback to be called when a new buffer (for encoding / decoding) needs to
+ * be allocated.
*/
- virtual void onPacketProduced(const core::ContentObject &content_object) = 0;
+ using BufferRequested = std::function<buffer(std::size_t size)>;
/**
- * Set callback to signal production protocol the repair packet is ready.
+ * @brief Get size of FEC header.
*/
- void setFECCallback(const RepairPacketsReady &on_repair_packet) {
- rep_packet_ready_callback_ = on_repair_packet;
+ virtual std::size_t getFecHeaderSize() = 0;
+
+ /**
+ * Set callback to call after packet encoding / decoding
+ */
+ template <typename Handler>
+ void setFECCallback(Handler &&callback) {
+ fec_callback_ = std::forward<Handler>(callback);
}
+ /**
+ * Set a callback to request a buffer.
+ */
+ template <typename Handler>
+ void setBufferCallback(Handler &&buffer_callback) {
+ buffer_callback_ = buffer_callback;
+ }
+
+ virtual void reset() = 0;
+
protected:
- RepairPacketsReady rep_packet_ready_callback_;
+ PacketsReady fec_callback_{0};
+ BufferRequested buffer_callback_{0};
};
/**
- * Interface classes to integrate FEC inside any consumer transport protocol
+ * Interface classes to integrate FEC inside any producer transport protocol
*/
-class ConsumerFECBase {
+class ProducerFEC : public virtual FECBase {
public:
+ virtual ~ProducerFEC() = default;
/**
- * Callback, to be called by implemrntations as soon as a packet is recovered.
+ * Producers will call this function upon production of a new packet.
*/
- using OnPacketsRecovered =
- std::function<void(std::vector<core::ContentObject::Ptr> &)>;
+ virtual void onPacketProduced(core::ContentObject &content_object,
+ uint32_t offset) = 0;
+};
- /**
- * Consumers will call this function when they receive a FEC packet.
- */
- virtual void onFECPacket(const core::ContentObject &content_object) = 0;
+/**
+ * Interface classes to integrate FEC inside any consumer transport protocol
+ */
+class ConsumerFEC : public virtual FECBase {
+ public:
+ virtual ~ConsumerFEC() = default;
/**
* Consumers will call this function when they receive a data packet
*/
- virtual void onDataPacket(const core::ContentObject &content_object) = 0;
-
- /**
- * Set callback to signal consumer protocol the repair packet is ready.
- */
- void setFECCallback(const OnPacketsRecovered &on_repair_packet) {
- packet_recovered_callback_ = on_repair_packet;
- }
-
- protected:
- OnPacketsRecovered packet_recovered_callback_;
+ virtual void onDataPacket(core::ContentObject &content_object,
+ uint32_t offset) = 0;
};
+} // namespace fec
} // namespace protocol
} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/fec_utils.h b/libtransport/src/protocols/fec_utils.h
new file mode 100644
index 000000000..d70ff1c09
--- /dev/null
+++ b/libtransport/src/protocols/fec_utils.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/config.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
+#include <protocols/fec/rs.h>
+
+#if ENABLE_RELY
+#include <protocols/fec/rely.h>
+#endif
+
+#include <functional>
+
+namespace transport {
+namespace protocol {
+
+namespace fec {
+
+#if ENABLE_RELY
+#define foreach_fec_type foreach_rs_fec_type foreach_rely_fec_type
+#else
+#define foreach_fec_type foreach_rs_fec_type
+#endif
+
+#define ENUM_FROM_MACRO(name, k, n) name##_K##k##_N##n
+#define ENUM_FROM_MACRO_STR(name, k, n) #name "_K" #k "_N" #n
+
+enum class FECType : uint8_t {
+#define _(name, k, n) ENUM_FROM_MACRO(name, k, n),
+ foreach_fec_type
+#undef _
+ UNKNOWN
+};
+
+#define ENUM_FROM_MACRO2(name, k, n) FECType::ENUM_FROM_MACRO(name, k, n)
+
+class FECUtils {
+ public:
+ static FECType fecTypeFromString(const char *fec_type) {
+#define _(name, k, n) \
+ do { \
+ if (strncmp(fec_type, ENUM_FROM_MACRO_STR(name, k, n), \
+ strlen(ENUM_FROM_MACRO_STR(name, k, n))) == 0) { \
+ return ENUM_FROM_MACRO2(name, k, n); \
+ } \
+ } while (0);
+ foreach_fec_type
+#undef _
+
+ return FECType::UNKNOWN;
+ }
+
+ static bool isFec(FECType fec_type, uint32_t index, uint32_t seq_offset = 0) {
+ switch (fec_type) {
+#define _(name, k, n) \
+ case ENUM_FROM_MACRO2(name, k, n): \
+ return FecInfo<Code<k, n>>::isFec(index - (seq_offset % n));
+
+ foreach_fec_type
+#undef _
+ default : return false;
+ }
+ }
+
+ static uint32_t nextSource(FECType fec_type, uint32_t index,
+ uint32_t seq_offset = 0) {
+ switch (fec_type) {
+#define _(name, k, n) \
+ case ENUM_FROM_MACRO2(name, k, n): \
+ return FecInfo<Code<k, n>>::nextSource(index) + (seq_offset % n);
+
+ foreach_fec_type
+#undef _
+ default : throw std::runtime_error("Unknown fec type");
+ }
+ }
+
+ static uint32_t getSourceSymbols(FECType fec_type) {
+ switch (fec_type) {
+#define _(name, k, n) \
+ case ENUM_FROM_MACRO2(name, k, n): \
+ return k;
+ foreach_fec_type
+#undef _
+ default : throw std::runtime_error("Unknown fec type");
+ }
+ }
+
+ static uint32_t getBlockSymbols(FECType fec_type) {
+ switch (fec_type) {
+#define _(name, k, n) \
+ case ENUM_FROM_MACRO2(name, k, n): \
+ return n;
+ foreach_fec_type
+#undef _
+ default : throw std::runtime_error("Unknown fec type");
+ }
+ }
+
+ static std::unique_ptr<ProducerFEC> getEncoder(FECType fec_type,
+ uint32_t seq_offset = 0) {
+ return factoryEncoder(fec_type, seq_offset);
+ }
+
+ static std::unique_ptr<ConsumerFEC> getDecoder(FECType fec_type,
+ uint32_t seq_offset = 0) {
+ return factoryDencoder(fec_type, seq_offset);
+ }
+
+ private:
+ static std::unique_ptr<ProducerFEC> factoryEncoder(FECType fec_type,
+ uint32_t seq_offset) {
+ switch (fec_type) {
+#define _(name, k, n) \
+ case ENUM_FROM_MACRO2(name, k, n): \
+ return std::make_unique<name##Encoder>(k, n, seq_offset);
+
+ foreach_fec_type
+#undef _
+ default : throw std::runtime_error("Unknown fec type");
+ }
+ }
+
+ static std::unique_ptr<ConsumerFEC> factoryDencoder(FECType fec_type,
+ uint32_t seq_offset) {
+ switch (fec_type) {
+#define _(name, k, n) \
+ case ENUM_FROM_MACRO2(name, k, n): \
+ return std::make_unique<name##Decoder>(k, n, seq_offset);
+
+ foreach_fec_type
+#undef _
+ default : throw std::runtime_error("Unknown fec type");
+ }
+ }
+}; // namespace fec
+
+} // namespace fec
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/protocols/incremental_indexer.h b/libtransport/src/protocols/incremental_indexer.h
deleted file mode 100644
index d7760f8e6..000000000
--- a/libtransport/src/protocols/incremental_indexer.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/errors/errors.h>
-#include <hicn/transport/interfaces/callbacks.h>
-#include <hicn/transport/auth/verifier.h>
-#include <hicn/transport/utils/literals.h>
-#include <implementation/socket_consumer.h>
-#include <protocols/indexer.h>
-#include <protocols/reassembly.h>
-
-#include <deque>
-
-namespace transport {
-
-namespace interface {
-class ConsumerSocket;
-}
-
-namespace protocol {
-
-class Reassembly;
-class TransportProtocol;
-
-class IncrementalIndexer : public Indexer {
- public:
- IncrementalIndexer(implementation::ConsumerSocket *icn_socket,
- TransportProtocol *transport, Reassembly *reassembly)
- : socket_(icn_socket),
- reassembly_(reassembly),
- transport_protocol_(transport),
- final_suffix_(std::numeric_limits<uint32_t>::max()),
- first_suffix_(0),
- next_download_suffix_(0),
- next_reassembly_suffix_(0),
- verifier_(nullptr) {
- if (reassembly_) {
- reassembly_->setIndexer(this);
- }
- socket_->getSocketOption(implementation::GeneralTransportOptions::VERIFIER,
- verifier_);
- }
-
- IncrementalIndexer(const IncrementalIndexer &) = delete;
-
- IncrementalIndexer(IncrementalIndexer &&other)
- : socket_(other.socket_),
- reassembly_(other.reassembly_),
- transport_protocol_(other.transport_protocol_),
- final_suffix_(other.final_suffix_),
- first_suffix_(other.first_suffix_),
- next_download_suffix_(other.next_download_suffix_),
- next_reassembly_suffix_(other.next_reassembly_suffix_),
- verifier_(nullptr) {
- if (reassembly_) {
- reassembly_->setIndexer(this);
- }
- socket_->getSocketOption(implementation::GeneralTransportOptions::VERIFIER,
- verifier_);
- }
-
- virtual ~IncrementalIndexer() {}
-
- TRANSPORT_ALWAYS_INLINE virtual void reset(
- std::uint32_t offset = 0) override {
- final_suffix_ = std::numeric_limits<uint32_t>::max();
- next_download_suffix_ = offset;
- next_reassembly_suffix_ = offset;
- }
-
- /**
- * Retrieve from the manifest the next suffix to retrieve.
- */
- TRANSPORT_ALWAYS_INLINE virtual uint32_t getNextSuffix() override {
- return next_download_suffix_ <= final_suffix_ ? next_download_suffix_++
- : IndexManager::invalid_index;
- }
-
- TRANSPORT_ALWAYS_INLINE virtual void setFirstSuffix(
- uint32_t suffix) override {
- first_suffix_ = suffix;
- }
-
- /**
- * Retrive the next segment to be reassembled.
- */
- TRANSPORT_ALWAYS_INLINE virtual uint32_t getNextReassemblySegment() override {
- return next_reassembly_suffix_ <= final_suffix_
- ? next_reassembly_suffix_++
- : IndexManager::invalid_index;
- }
-
- TRANSPORT_ALWAYS_INLINE virtual bool isFinalSuffixDiscovered() override {
- return final_suffix_ != std::numeric_limits<uint32_t>::max();
- }
-
- TRANSPORT_ALWAYS_INLINE virtual uint32_t getFinalSuffix() override {
- return final_suffix_;
- }
-
- void onContentObject(core::Interest &interest,
- core::ContentObject &content_object) override;
-
- TRANSPORT_ALWAYS_INLINE void setReassembly(Reassembly *reassembly) {
- reassembly_ = reassembly;
-
- if (reassembly_) {
- reassembly_->setIndexer(this);
- }
- }
-
- protected:
- implementation::ConsumerSocket *socket_;
- Reassembly *reassembly_;
- TransportProtocol *transport_protocol_;
- uint32_t final_suffix_;
- uint32_t first_suffix_;
- uint32_t next_download_suffix_;
- uint32_t next_reassembly_suffix_;
- std::shared_ptr<auth::Verifier> verifier_;
-};
-
-} // namespace protocol
-} // namespace transport
diff --git a/libtransport/src/protocols/incremental_indexer.cc b/libtransport/src/protocols/incremental_indexer_bytestream.cc
index 95daa0a3e..cc302a98a 100644
--- a/libtransport/src/protocols/incremental_indexer.cc
+++ b/libtransport/src/protocols/incremental_indexer_bytestream.cc
@@ -15,18 +15,21 @@
#include <hicn/transport/interfaces/socket_consumer.h>
#include <protocols/errors.h>
-#include <protocols/incremental_indexer.h>
+#include <protocols/incremental_indexer_bytestream.h>
#include <protocols/transport_protocol.h>
namespace transport {
namespace protocol {
void IncrementalIndexer::onContentObject(core::Interest &interest,
- core::ContentObject &content_object) {
+ core::ContentObject &content_object,
+ bool reassembly) {
using namespace interface;
- TRANSPORT_LOGD("Received content %s",
- content_object.getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Received content " << content_object.getName();
+
+ assert(reassembly_);
if (TRANSPORT_EXPECT_FALSE(content_object.testRst())) {
final_suffix_ = content_object.getName().getSuffix();
@@ -36,16 +39,22 @@ void IncrementalIndexer::onContentObject(core::Interest &interest,
switch (ret) {
case auth::VerificationPolicy::ACCEPT: {
- reassembly_->reassemble(content_object);
+ if (reassembly) {
+ reassembly_->reassemble(content_object);
+ }
break;
}
+
case auth::VerificationPolicy::UNKNOWN:
case auth::VerificationPolicy::DROP: {
- transport_protocol_->onPacketDropped(interest, content_object);
+ transport_->onPacketDropped(
+ interest, content_object,
+ make_error_code(protocol_error::verification_failed));
break;
}
+
case auth::VerificationPolicy::ABORT: {
- transport_protocol_->onContentReassembled(
+ transport_->onContentReassembled(
make_error_code(protocol_error::session_aborted));
break;
}
diff --git a/libtransport/src/protocols/incremental_indexer_bytestream.h b/libtransport/src/protocols/incremental_indexer_bytestream.h
new file mode 100644
index 000000000..c6a669629
--- /dev/null
+++ b/libtransport/src/protocols/incremental_indexer_bytestream.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/interfaces/callbacks.h>
+#include <hicn/transport/utils/literals.h>
+#include <implementation/socket_consumer.h>
+#include <protocols/indexer.h>
+#include <protocols/reassembly.h>
+
+#include <deque>
+
+namespace transport {
+
+namespace interface {
+class ConsumerSocket;
+}
+
+namespace protocol {
+
+class Reassembly;
+class TransportProtocol;
+
+class IncrementalIndexer : public Indexer {
+ public:
+ IncrementalIndexer(implementation::ConsumerSocket *icn_socket,
+ TransportProtocol *transport)
+ : Indexer(icn_socket, transport),
+ final_suffix_(Indexer::invalid_index),
+ first_suffix_(0),
+ next_download_suffix_(0),
+ next_reassembly_suffix_(0) {}
+
+ IncrementalIndexer(const IncrementalIndexer &other) = delete;
+
+ IncrementalIndexer(IncrementalIndexer &&other)
+ : Indexer(std::forward<Indexer>(other)),
+ final_suffix_(other.final_suffix_),
+ first_suffix_(other.first_suffix_),
+ next_download_suffix_(other.next_download_suffix_),
+ next_reassembly_suffix_(other.next_reassembly_suffix_) {}
+
+ virtual ~IncrementalIndexer() {}
+
+ virtual void reset() override {
+ final_suffix_ = Indexer::invalid_index;
+ next_download_suffix_ = first_suffix_;
+ next_reassembly_suffix_ = first_suffix_;
+ }
+
+ virtual uint32_t checkNextSuffix() override {
+ return next_download_suffix_ <= final_suffix_ ? next_download_suffix_
+ : Indexer::invalid_index;
+ }
+
+ virtual uint32_t getNextSuffix() override {
+ return next_download_suffix_ <= final_suffix_ ? next_download_suffix_++
+ : Indexer::invalid_index;
+ }
+
+ virtual void setFirstSuffix(uint32_t suffix) override {
+ first_suffix_ = suffix;
+ }
+
+ uint32_t getFirstSuffix() override { return first_suffix_; }
+
+ virtual uint32_t jumpToIndex(uint32_t index) override {
+ next_download_suffix_ = index;
+ return next_download_suffix_;
+ }
+
+ /**
+ * Retrive the next segment to be reassembled.
+ */
+ virtual uint32_t getNextReassemblySegment() override {
+ return next_reassembly_suffix_ <= final_suffix_ ? next_reassembly_suffix_++
+ : Indexer::invalid_index;
+ }
+
+ virtual bool isFinalSuffixDiscovered() override {
+ return final_suffix_ != Indexer::invalid_index;
+ }
+
+ virtual uint32_t getFinalSuffix() override { return final_suffix_; }
+
+ void enableFec(fec::FECType fec_type) override {}
+
+ void disableFec() override {}
+
+ void setNFec(uint32_t n_fec) override {}
+ virtual uint32_t getNFec() override { return 0; }
+
+ virtual void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object,
+ bool reassembly) override;
+
+ protected:
+ uint32_t final_suffix_;
+ uint32_t first_suffix_;
+ uint32_t next_download_suffix_;
+ uint32_t next_reassembly_suffix_;
+};
+
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/protocols/index_manager_bytestream.cc b/libtransport/src/protocols/index_manager_bytestream.cc
new file mode 100644
index 000000000..c78dc634d
--- /dev/null
+++ b/libtransport/src/protocols/index_manager_bytestream.cc
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <protocols/index_manager_bytestream.h>
+#include <protocols/manifest_incremental_indexer_bytestream.h>
+#include <protocols/transport_protocol.h>
+
+namespace transport {
+namespace protocol {
+
+IndexManager::IndexManager(implementation::ConsumerSocket *icn_socket,
+ TransportProtocol *transport)
+ : IncrementalIndexer(icn_socket, transport),
+ indexer_(std::make_unique<IncrementalIndexer>(icn_socket, transport)),
+ first_segment_received_(false) {}
+
+void IndexManager::onContentObject(core::Interest &interest,
+ core::ContentObject &content_object,
+ bool reassembly) {
+ if (first_segment_received_) {
+ return indexer_->onContentObject(interest, content_object, reassembly);
+ } else {
+ std::uint32_t segment_number = interest.getName().getSuffix();
+
+ if (segment_number == 0) {
+ // Check if manifest
+ if (content_object.getPayloadType() == core::PayloadType::MANIFEST) {
+ IncrementalIndexer *indexer =
+ static_cast<IncrementalIndexer *>(indexer_.release());
+ indexer_ =
+ std::make_unique<ManifestIncrementalIndexer>(std::move(*indexer));
+ delete indexer;
+ }
+
+ indexer_->onContentObject(interest, content_object);
+ auto it = interest_data_set_.begin();
+ while (it != interest_data_set_.end()) {
+ indexer_->onContentObject(*it->first, *it->second);
+ it = interest_data_set_.erase(it);
+ }
+
+ first_segment_received_ = true;
+ } else {
+ interest_data_set_.emplace(interest.shared_from_this(),
+ content_object.shared_from_this());
+ }
+ }
+}
+
+void IndexManager::reset() {
+ indexer_ = std::make_unique<IncrementalIndexer>(socket_, transport_);
+ indexer_->setReassembly(this->reassembly_);
+ indexer_->reset();
+ first_segment_received_ = false;
+ interest_data_set_.clear();
+}
+
+} // namespace protocol
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/index_manager_bytestream.h b/libtransport/src/protocols/index_manager_bytestream.h
new file mode 100644
index 000000000..e14c8845b
--- /dev/null
+++ b/libtransport/src/protocols/index_manager_bytestream.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <protocols/incremental_indexer_bytestream.h>
+
+#include <list>
+
+namespace transport {
+
+namespace implementation {
+class ConsumerSocket;
+}
+
+namespace protocol {
+
+class TransportProtocol;
+
+class IndexManager : public IncrementalIndexer {
+ public:
+ IndexManager(implementation::ConsumerSocket *icn_socket,
+ TransportProtocol *transport);
+
+ uint32_t getNextSuffix() override { return indexer_->getNextSuffix(); }
+
+ void setFirstSuffix(uint32_t suffix) override {
+ indexer_->setFirstSuffix(suffix);
+ }
+
+ uint32_t getFirstSuffix() override { return indexer_->getFirstSuffix(); }
+
+ uint32_t getNextReassemblySegment() override {
+ return indexer_->getNextReassemblySegment();
+ }
+
+ bool isFinalSuffixDiscovered() override {
+ return indexer_->isFinalSuffixDiscovered();
+ }
+
+ uint32_t getFinalSuffix() override { return indexer_->getFinalSuffix(); }
+
+ uint32_t jumpToIndex(uint32_t index) override {
+ return indexer_->jumpToIndex(index);
+ }
+
+ void setNFec(uint32_t n_fec) override { return indexer_->setNFec(n_fec); }
+ uint32_t getNFec() override { return indexer_->getNFec(); }
+
+ void enableFec(fec::FECType fec_type) override {
+ return indexer_->enableFec(fec_type);
+ }
+
+ double getFecOverhead() override { return indexer_->getFecOverhead(); }
+
+ double getMaxFecOverhead() override { return indexer_->getMaxFecOverhead(); }
+
+ void disableFec() override { return indexer_->disableFec(); }
+
+ void reset() override;
+
+ void setReassembly(Reassembly *reassembly) override {
+ Indexer::setReassembly(reassembly);
+ indexer_->setReassembly(reassembly);
+ }
+
+ void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object,
+ bool reassembly) override;
+
+ private:
+ std::unique_ptr<Indexer> indexer_;
+ bool first_segment_received_;
+ std::set<std::pair<core::Interest::Ptr, core::ContentObject::Ptr>>
+ interest_data_set_;
+};
+
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/protocols/indexer.cc b/libtransport/src/protocols/indexer.cc
index 1379a609c..8d4cf04d7 100644
--- a/libtransport/src/protocols/indexer.cc
+++ b/libtransport/src/protocols/indexer.cc
@@ -13,61 +13,29 @@
* limitations under the License.
*/
-#include <hicn/transport/utils/branch_prediction.h>
-#include <protocols/incremental_indexer.h>
+#include <implementation/socket_consumer.h>
#include <protocols/indexer.h>
-#include <protocols/manifest_incremental_indexer.h>
namespace transport {
-namespace protocol {
-IndexManager::IndexManager(implementation::ConsumerSocket *icn_socket,
- TransportProtocol *transport, Reassembly *reassembly)
- : indexer_(std::make_unique<IncrementalIndexer>(icn_socket, transport,
- reassembly)),
- first_segment_received_(false),
- icn_socket_(icn_socket),
- transport_(transport),
- reassembly_(reassembly) {}
+namespace protocol {
-void IndexManager::onContentObject(core::Interest &interest,
- core::ContentObject &content_object) {
- if (first_segment_received_) {
- indexer_->onContentObject(interest, content_object);
- } else {
- std::uint32_t segment_number = interest.getName().getSuffix();
+using namespace interface;
- if (segment_number == 0) {
- // Check if manifest
- if (content_object.getPayloadType() == core::PayloadType::MANIFEST) {
- IncrementalIndexer *indexer =
- static_cast<IncrementalIndexer *>(indexer_.release());
- indexer_ =
- std::make_unique<ManifestIncrementalIndexer>(std::move(*indexer));
- delete indexer;
- }
+const constexpr uint32_t Indexer::invalid_index;
- indexer_->onContentObject(interest, content_object);
- auto it = interest_data_set_.begin();
- while (it != interest_data_set_.end()) {
- indexer_->onContentObject(*it->first, *it->second);
- it = interest_data_set_.erase(it);
- }
+Indexer::Indexer(implementation::ConsumerSocket *socket,
+ TransportProtocol *transport)
+ : socket_(socket), transport_(transport) {
+ setVerifier();
+}
- first_segment_received_ = true;
- } else {
- interest_data_set_.emplace(interest.shared_from_this(),
- content_object.shared_from_this());
- }
+void Indexer::setVerifier() {
+ if (socket_) {
+ socket_->getSocketOption(GeneralTransportOptions::VERIFIER, verifier_);
}
}
-void IndexManager::reset(std::uint32_t offset) {
- indexer_ = std::make_unique<IncrementalIndexer>(icn_socket_, transport_,
- reassembly_);
- first_segment_received_ = false;
- interest_data_set_.clear();
-}
+} // end namespace protocol
-} // namespace protocol
-} // namespace transport
+} // end namespace transport
diff --git a/libtransport/src/protocols/indexer.h b/libtransport/src/protocols/indexer.h
index 49e22a4cf..7e3a52fb0 100644
--- a/libtransport/src/protocols/indexer.h
+++ b/libtransport/src/protocols/indexer.h
@@ -17,6 +17,7 @@
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
+#include <protocols/fec_utils.h>
#include <set>
@@ -33,66 +34,80 @@ class TransportProtocol;
class Indexer {
public:
+ static const constexpr uint32_t invalid_index =
+ (std::numeric_limits<uint32_t>::max() - 1);
+
+ Indexer(implementation::ConsumerSocket *socket, TransportProtocol *transport);
+
virtual ~Indexer() = default;
/**
- * Retrieve from the manifest the next suffix to retrieve.
+ * Suffix getters
*/
+ virtual uint32_t checkNextSuffix() = 0;
virtual uint32_t getNextSuffix() = 0;
+ virtual uint32_t getNextReassemblySegment() = 0;
+ /**
+ * Set first suffix from where to start.
+ */
virtual void setFirstSuffix(uint32_t suffix) = 0;
+ virtual uint32_t getFirstSuffix() = 0;
/**
- * Retrive the next segment to be reassembled.
+ * Functions to set/enable/disable fec
*/
- virtual uint32_t getNextReassemblySegment() = 0;
+ virtual void setNFec(uint32_t n_fec) = 0;
+ virtual uint32_t getNFec() = 0;
+ virtual void enableFec(fec::FECType fec_type) = 0;
+ virtual void disableFec() = 0;
+ virtual bool isFec(uint32_t index) { return false; }
+ virtual double getFecOverhead() { return 0.0; }
+ virtual double getMaxFecOverhead() { return 0.0; }
+ /**
+ * Final suffix helpers.
+ */
virtual bool isFinalSuffixDiscovered() = 0;
-
virtual uint32_t getFinalSuffix() = 0;
- virtual void reset(std::uint32_t offset = 0) = 0;
-
- virtual void onContentObject(core::Interest &interest,
- core::ContentObject &content_object) = 0;
-};
-
-class IndexManager : Indexer {
- public:
- static constexpr uint32_t invalid_index = ~0;
-
- IndexManager(implementation::ConsumerSocket *icn_socket,
- TransportProtocol *transport, Reassembly *reassembly);
-
- uint32_t getNextSuffix() override { return indexer_->getNextSuffix(); }
-
- void setFirstSuffix(uint32_t suffix) override {
- indexer_->setFirstSuffix(suffix);
- }
-
- uint32_t getNextReassemblySegment() override {
- return indexer_->getNextReassemblySegment();
+ /**
+ * Set reassembly protocol
+ */
+ virtual void setReassembly(Reassembly *reassembly) {
+ reassembly_ = reassembly;
}
- bool isFinalSuffixDiscovered() override {
- return indexer_->isFinalSuffixDiscovered();
- }
+ /**
+ * Set verifier using socket
+ */
+ virtual void setVerifier();
- uint32_t getFinalSuffix() override { return indexer_->getFinalSuffix(); }
+ /**
+ * Jump to suffix. This may be useful if, for any protocol dependent
+ * mechanism, we need to suddenly change current suffix. This does not modify
+ * the way suffixes re incremented/decremented (that's part of the
+ * implementation).
+ */
+ virtual uint32_t jumpToIndex(uint32_t index) = 0;
- void reset(std::uint32_t offset = 0) override;
+ /**
+ * Reset the indexer.
+ */
+ virtual void reset() = 0;
- void onContentObject(core::Interest &interest,
- core::ContentObject &content_object) override;
+ /**
+ * Process incoming content objects.
+ */
+ virtual void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object,
+ bool reassembly = true) = 0;
- private:
- std::unique_ptr<Indexer> indexer_;
- bool first_segment_received_;
- std::set<std::pair<core::Interest::Ptr, core::ContentObject::Ptr>>
- interest_data_set_;
- implementation::ConsumerSocket *icn_socket_;
+ protected:
+ implementation::ConsumerSocket *socket_;
TransportProtocol *transport_;
Reassembly *reassembly_;
+ std::shared_ptr<auth::Verifier> verifier_;
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/manifest_incremental_indexer.cc b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
index a6312ca90..168aa57af 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer.cc
+++ b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
@@ -15,7 +15,7 @@
#include <implementation/socket_consumer.h>
#include <protocols/errors.h>
-#include <protocols/manifest_incremental_indexer.h>
+#include <protocols/manifest_incremental_indexer_bytestream.h>
#include <protocols/transport_protocol.h>
#include <cmath>
@@ -28,26 +28,26 @@ namespace protocol {
using namespace interface;
ManifestIncrementalIndexer::ManifestIncrementalIndexer(
- implementation::ConsumerSocket *icn_socket, TransportProtocol *transport,
- Reassembly *reassembly)
- : IncrementalIndexer(icn_socket, transport, reassembly),
+ implementation::ConsumerSocket *icn_socket, TransportProtocol *transport)
+ : IncrementalIndexer(icn_socket, transport),
suffix_strategy_(utils::SuffixStrategyFactory::getSuffixStrategy(
NextSegmentCalculationStrategy::INCREMENTAL, next_download_suffix_,
0)) {}
void ManifestIncrementalIndexer::onContentObject(
- core::Interest &interest, core::ContentObject &content_object) {
+ core::Interest &interest, core::ContentObject &content_object,
+ bool reassembly) {
switch (content_object.getPayloadType()) {
case PayloadType::DATA: {
- TRANSPORT_LOGD("Received content %s",
- content_object.getName().toString().c_str());
- onUntrustedContentObject(interest, content_object);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Received content " << content_object.getName();
+ onUntrustedContentObject(interest, content_object, reassembly);
break;
}
case PayloadType::MANIFEST: {
- TRANSPORT_LOGD("Received manifest %s",
- content_object.getName().toString().c_str());
- onUntrustedManifest(interest, content_object);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Received manifest " << content_object.getName();
+ onUntrustedManifest(interest, content_object, reassembly);
break;
}
default: {
@@ -57,7 +57,8 @@ void ManifestIncrementalIndexer::onContentObject(
}
void ManifestIncrementalIndexer::onUntrustedManifest(
- core::Interest &interest, core::ContentObject &content_object) {
+ core::Interest &interest, core::ContentObject &content_object,
+ bool reassembly) {
auto manifest =
std::make_unique<ContentObjectManifest>(std::move(content_object));
@@ -66,16 +67,17 @@ void ManifestIncrementalIndexer::onUntrustedManifest(
manifest->decode();
if (policy != auth::VerificationPolicy::ACCEPT) {
- transport_protocol_->onContentReassembled(
+ transport_->onContentReassembled(
make_error_code(protocol_error::session_aborted));
return;
}
- processTrustedManifest(interest, std::move(manifest));
+ processTrustedManifest(interest, std::move(manifest), reassembly);
}
void ManifestIncrementalIndexer::processTrustedManifest(
- core::Interest &interest, std::unique_ptr<ContentObjectManifest> manifest) {
+ core::Interest &interest, std::unique_ptr<ContentObjectManifest> manifest,
+ bool reassembly) {
if (TRANSPORT_EXPECT_FALSE(manifest->getVersion() !=
core::ManifestVersion::VERSION_1)) {
throw errors::RuntimeException("Received manifest with unknown version.");
@@ -89,7 +91,7 @@ void ManifestIncrementalIndexer::processTrustedManifest(
std::vector<auth::PacketPtr> packets;
// Convert the received manifest to a map of packet suffixes to hashes
- std::unordered_map<auth::Suffix, auth::HashEntry> current_manifest =
+ auth::Verifier::SuffixMap current_manifest =
core::ContentObjectManifest::getSuffixMap(manifest.get());
// Update 'suffix_map_' with new hashes from the received manifest and
@@ -102,26 +104,31 @@ void ManifestIncrementalIndexer::processTrustedManifest(
continue;
}
- packets.push_back(unverified_segments_[it->first].second.get());
+ packets.push_back(std::get<1>(unverified_segments_[it->first]).get());
it++;
}
// Verify unverified segments using the received manifest
- std::vector<auth::VerificationPolicy> policies =
+ auth::Verifier::PolicyMap policies =
verifier_->verifyPackets(packets, current_manifest);
for (unsigned int i = 0; i < packets.size(); ++i) {
auth::Suffix suffix = packets[i]->getName().getSuffix();
- if (policies[i] != auth::VerificationPolicy::UNKNOWN) {
- unverified_segments_.erase(suffix);
+ auto it = unverified_segments_.find(suffix);
+
+ if (policies[suffix] != auth::VerificationPolicy::UNKNOWN) {
+ unverified_segments_.erase(it);
+ continue;
}
- applyPolicy(*unverified_segments_[suffix].first,
- *unverified_segments_[suffix].second, policies[i]);
+ applyPolicy(*std::get<0>(it->second), *std::get<1>(it->second),
+ std::get<2>(it->second), policies[suffix]);
}
- reassembly_->reassemble(std::move(manifest));
+ if (reassembly) {
+ reassembly_->reassemble(std::move(manifest));
+ }
break;
}
case core::ManifestType::FLIC_MANIFEST: {
@@ -134,15 +141,16 @@ void ManifestIncrementalIndexer::processTrustedManifest(
}
void ManifestIncrementalIndexer::onUntrustedContentObject(
- Interest &interest, ContentObject &content_object) {
+ Interest &interest, ContentObject &content_object, bool reassembly) {
auth::Suffix suffix = content_object.getName().getSuffix();
auth::VerificationPolicy policy =
verifier_->verifyPackets(&content_object, suffix_map_);
switch (policy) {
case auth::VerificationPolicy::UNKNOWN: {
- unverified_segments_[suffix] = std::make_pair(
- interest.shared_from_this(), content_object.shared_from_this());
+ unverified_segments_[suffix] =
+ std::make_tuple(interest.shared_from_this(),
+ content_object.shared_from_this(), reassembly);
break;
}
default: {
@@ -151,32 +159,43 @@ void ManifestIncrementalIndexer::onUntrustedContentObject(
}
}
- applyPolicy(interest, content_object, policy);
+ applyPolicy(interest, content_object, reassembly, policy);
}
void ManifestIncrementalIndexer::applyPolicy(
core::Interest &interest, core::ContentObject &content_object,
- auth::VerificationPolicy policy) {
+ bool reassembly, auth::VerificationPolicy policy) {
+ assert(reassembly_);
switch (policy) {
case auth::VerificationPolicy::ACCEPT: {
- reassembly_->reassemble(content_object);
+ if (reassembly && !reassembly_->reassembleUnverified()) {
+ reassembly_->reassemble(content_object);
+ }
break;
}
case auth::VerificationPolicy::DROP: {
- transport_protocol_->onPacketDropped(interest, content_object);
+ transport_->onPacketDropped(
+ interest, content_object,
+ make_error_code(protocol_error::verification_failed));
break;
}
case auth::VerificationPolicy::ABORT: {
- transport_protocol_->onContentReassembled(
+ transport_->onContentReassembled(
make_error_code(protocol_error::session_aborted));
break;
}
- default: {
- break;
+ case auth::VerificationPolicy::UNKNOWN: {
+ if (reassembly && reassembly_->reassembleUnverified()) {
+ reassembly_->reassemble(content_object);
+ }
}
}
}
+uint32_t ManifestIncrementalIndexer::checkNextSuffix() {
+ return suffix_strategy_->getNextSuffix();
+}
+
uint32_t ManifestIncrementalIndexer::getNextSuffix() {
auto ret = suffix_strategy_->getNextSuffix();
@@ -186,7 +205,7 @@ uint32_t ManifestIncrementalIndexer::getNextSuffix() {
return ret;
}
- return IndexManager::invalid_index;
+ return Indexer::invalid_index;
}
uint32_t ManifestIncrementalIndexer::getFinalSuffix() {
@@ -199,7 +218,7 @@ bool ManifestIncrementalIndexer::isFinalSuffixDiscovered() {
uint32_t ManifestIncrementalIndexer::getNextReassemblySegment() {
if (suffix_queue_.empty()) {
- return IndexManager::invalid_index;
+ return Indexer::invalid_index;
}
auto ret = suffix_queue_.front();
@@ -207,13 +226,13 @@ uint32_t ManifestIncrementalIndexer::getNextReassemblySegment() {
return ret;
}
-void ManifestIncrementalIndexer::reset(std::uint32_t offset) {
- IncrementalIndexer::reset(offset);
+void ManifestIncrementalIndexer::reset() {
+ IncrementalIndexer::reset();
suffix_map_.clear();
unverified_segments_.clear();
SuffixQueue empty;
std::swap(suffix_queue_, empty);
- suffix_strategy_->reset(offset);
+ suffix_strategy_->reset(first_suffix_);
}
} // namespace protocol
diff --git a/libtransport/src/protocols/manifest_incremental_indexer.h b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
index 1bb76eb87..d8cf5892f 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer.h
+++ b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
@@ -17,7 +17,7 @@
#include <hicn/transport/auth/common.h>
#include <implementation/socket.h>
-#include <protocols/incremental_indexer.h>
+#include <protocols/incremental_indexer_bytestream.h>
#include <utils/suffix_strategy.h>
#include <list>
@@ -31,11 +31,10 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
public:
using SuffixQueue = std::queue<uint32_t>;
using InterestContentPair =
- std::pair<core::Interest::Ptr, core::ContentObject::Ptr>;
+ std::tuple<core::Interest::Ptr, core::ContentObject::Ptr, bool>;
ManifestIncrementalIndexer(implementation::ConsumerSocket *icn_socket,
- TransportProtocol *transport,
- Reassembly *reassembly);
+ TransportProtocol *transport);
ManifestIncrementalIndexer(IncrementalIndexer &&indexer)
: IncrementalIndexer(std::move(indexer)),
@@ -49,10 +48,13 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
virtual ~ManifestIncrementalIndexer() = default;
- void reset(std::uint32_t offset = 0) override;
+ void reset() override;
void onContentObject(core::Interest &interest,
- core::ContentObject &content_object) override;
+ core::ContentObject &content_object,
+ bool reassembly) override;
+
+ uint32_t checkNextSuffix() override;
uint32_t getNextSuffix() override;
@@ -67,18 +69,21 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
SuffixQueue suffix_queue_;
// Hash verification
- std::unordered_map<auth::Suffix, auth::HashEntry> suffix_map_;
+ auth::Verifier::SuffixMap suffix_map_;
std::unordered_map<auth::Suffix, InterestContentPair> unverified_segments_;
private:
void onUntrustedManifest(core::Interest &interest,
- core::ContentObject &content_object);
+ core::ContentObject &content_object,
+ bool reassembly);
void processTrustedManifest(core::Interest &interest,
- std::unique_ptr<ContentObjectManifest> manifest);
+ std::unique_ptr<ContentObjectManifest> manifest,
+ bool reassembly);
void onUntrustedContentObject(core::Interest &interest,
- core::ContentObject &content_object);
+ core::ContentObject &content_object,
+ bool reassembly);
void applyPolicy(core::Interest &interest,
- core::ContentObject &content_object,
+ core::ContentObject &content_object, bool reassembly,
auth::VerificationPolicy policy);
};
diff --git a/libtransport/src/protocols/packet_manager.h b/libtransport/src/protocols/packet_manager.h
deleted file mode 100644
index a552607ea..000000000
--- a/libtransport/src/protocols/packet_manager.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/utils/object_pool.h>
-
-namespace transport {
-
-namespace protocol {
-
-using namespace core;
-
-template <typename PacketType, std::size_t packet_pool_size = 4096>
-class PacketManager {
- static_assert(std::is_base_of<Packet, PacketType>::value,
- "The packet manager support just Interest and Data.");
-
- public:
- PacketManager(std::size_t size = packet_pool_size) : size_(0) {
- // Create pool of interests
- increasePoolSize(size);
- }
-
- TRANSPORT_ALWAYS_INLINE void increasePoolSize(std::size_t size) {
- for (std::size_t i = 0; i < size; i++) {
- interest_pool_.add(new PacketType());
- }
-
- size_ += size;
- }
-
- TRANSPORT_ALWAYS_INLINE typename PacketType::Ptr getPacket() {
- auto result = interest_pool_.get();
-
- while (TRANSPORT_EXPECT_FALSE(!result.first)) {
- // Add packets to the pool
- increasePoolSize(size_);
- result = interest_pool_.get();
- }
-
- result.second->resetPayload();
- return std::move(result.second);
- }
-
- private:
- utils::ObjectPool<PacketType> interest_pool_;
- std::size_t size_;
-};
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/prod_protocol_bytestream.cc b/libtransport/src/protocols/prod_protocol_bytestream.cc
index 6bd989fe4..f659cb37c 100644
--- a/libtransport/src/protocols/prod_protocol_bytestream.cc
+++ b/libtransport/src/protocols/prod_protocol_bytestream.cc
@@ -87,11 +87,6 @@ uint32_t ByteStreamProductionProtocol::produceStream(
auth::CryptoHashType hash_algo;
socket_->getSocketOption(GeneralTransportOptions::HASH_ALGORITHM, hash_algo);
- // Use manifest
- bool making_manifest;
- socket_->getSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- making_manifest);
-
// Suffix calculation strategy
core::NextSegmentCalculationStrategy _suffix_strategy;
socket_->getSocketOption(GeneralTransportOptions::SUFFIX_STRATEGY,
@@ -99,9 +94,6 @@ uint32_t ByteStreamProductionProtocol::produceStream(
auto suffix_strategy = utils::SuffixStrategyFactory::getSuffixStrategy(
_suffix_strategy, start_offset);
- std::shared_ptr<auth::Signer> signer;
- socket_->getSocketOption(GeneralTransportOptions::SIGNER, signer);
-
auto buffer_size = buffer->length();
int bytes_segmented = 0;
std::size_t header_size;
@@ -115,8 +107,8 @@ uint32_t ByteStreamProductionProtocol::produceStream(
bool is_last_manifest = false;
// TODO Manifest may still be used for indexing
- if (making_manifest && !signer) {
- TRANSPORT_LOGE("Making manifests without setting producer identity.");
+ if (making_manifest_ && !signer_) {
+ LOG(FATAL) << "Making manifests without setting producer identity.";
}
core::Packet::Format hf_format = core::Packet::Format::HF_UNSPEC;
@@ -134,13 +126,13 @@ uint32_t ByteStreamProductionProtocol::produceStream(
}
format = hf_format;
- if (making_manifest) {
+ if (making_manifest_) {
manifest_header_size = core::Packet::getHeaderSizeFromFormat(
- signer ? hf_format_ah : hf_format,
- signer ? signer->getSignatureSize() : 0);
- } else if (signer) {
+ signer_ ? hf_format_ah : hf_format,
+ signer_ ? signer_->getSignatureFieldSize() : 0);
+ } else if (signer_) {
format = hf_format_ah;
- signature_length = signer->getSignatureSize();
+ signature_length = signer_->getSignatureFieldSize();
}
header_size = core::Packet::getHeaderSizeFromFormat(format, signature_length);
@@ -152,7 +144,7 @@ uint32_t ByteStreamProductionProtocol::produceStream(
}
// TODO allocate space for all the headers
- if (making_manifest) {
+ if (making_manifest_) {
uint32_t segment_in_manifest = static_cast<uint32_t>(
std::floor(double(data_packet_size - manifest_header_size -
ContentObjectManifest::getManifestHeaderSize()) /
@@ -166,7 +158,7 @@ uint32_t ByteStreamProductionProtocol::produceStream(
name.setSuffix(suffix_strategy->getNextManifestSuffix()),
core::ManifestVersion::VERSION_1, core::ManifestType::INLINE_MANIFEST,
hash_algo, is_last_manifest, name, _suffix_strategy,
- signer ? signer->getSignatureSize() : 0));
+ signer_ ? signer_->getSignatureFieldSize() : 0));
manifest->setLifetime(content_object_expiry_time);
if (is_last) {
@@ -178,27 +170,26 @@ uint32_t ByteStreamProductionProtocol::produceStream(
for (unsigned int packaged_segments = 0;
packaged_segments < number_of_segments; packaged_segments++) {
- if (making_manifest) {
+ if (making_manifest_) {
if (manifest->estimateManifestSize(2) >
data_packet_size - manifest_header_size) {
manifest->encode();
// If identity set, sign manifest
- if (signer) {
- signer->signPacket(manifest.get());
+ if (signer_) {
+ signer_->signPacket(manifest.get());
}
// Send the current manifest
passContentObjectToCallbacks(manifest);
- TRANSPORT_LOGD("Send manifest %s",
- manifest->getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send manifest " << manifest->getName();
// Send content objects stored in the queue
while (!content_queue_.empty()) {
passContentObjectToCallbacks(content_queue_.front());
- TRANSPORT_LOGD("Send content %s",
- content_queue_.front()->getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Send content " << content_queue_.front()->getName();
content_queue_.pop();
}
@@ -209,7 +200,8 @@ uint32_t ByteStreamProductionProtocol::produceStream(
name.setSuffix(suffix_strategy->getNextManifestSuffix()),
core::ManifestVersion::VERSION_1,
core::ManifestType::INLINE_MANIFEST, hash_algo, is_last_manifest,
- name, _suffix_strategy, signer ? signer->getSignatureSize() : 0));
+ name, _suffix_strategy,
+ signer_ ? signer_->getSignatureFieldSize() : 0));
manifest->setLifetime(content_object_expiry_time);
manifest->setFinalBlockNumber(
@@ -221,7 +213,7 @@ uint32_t ByteStreamProductionProtocol::produceStream(
auto content_suffix = suffix_strategy->getNextContentSuffix();
auto content_object = std::make_shared<ContentObject>(
name.setSuffix(content_suffix), format,
- signer && !making_manifest ? signer->getSignatureSize() : 0);
+ signer_ && !making_manifest_ ? signer_->getSignatureFieldSize() : 0);
content_object->setLifetime(content_object_expiry_time);
auto b = buffer->cloneOne();
@@ -232,7 +224,7 @@ uint32_t ByteStreamProductionProtocol::produceStream(
b->append(buffer_size - bytes_segmented);
bytes_segmented += (int)(buffer_size - bytes_segmented);
- if (is_last && making_manifest) {
+ if (is_last && making_manifest_) {
is_last_manifest = true;
} else if (is_last) {
content_object->setRst();
@@ -245,39 +237,39 @@ uint32_t ByteStreamProductionProtocol::produceStream(
content_object->appendPayload(std::move(b));
- if (making_manifest) {
+ if (making_manifest_) {
using namespace std::chrono_literals;
auth::CryptoHash hash = content_object->computeDigest(hash_algo);
manifest->addSuffixHash(content_suffix, hash);
content_queue_.push(content_object);
} else {
- if (signer) {
- signer->signPacket(content_object.get());
+ if (signer_) {
+ signer_->signPacket(content_object.get());
}
passContentObjectToCallbacks(content_object);
- TRANSPORT_LOGD("Send content %s",
- content_object->getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Send content " << content_object->getName();
}
}
- if (making_manifest) {
+ if (making_manifest_) {
if (is_last_manifest) {
manifest->setFinalManifest(is_last_manifest);
}
manifest->encode();
- if (signer) {
- signer->signPacket(manifest.get());
+ if (signer_) {
+ signer_->signPacket(manifest.get());
}
passContentObjectToCallbacks(manifest);
- TRANSPORT_LOGD("Send manifest %s", manifest->getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send manifest " << manifest->getName();
while (!content_queue_.empty()) {
passContentObjectToCallbacks(content_queue_.front());
- TRANSPORT_LOGD("Send content %s",
- content_queue_.front()->getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Send content " << content_queue_.front()->getName();
content_queue_.pop();
}
}
@@ -356,14 +348,14 @@ void ByteStreamProductionProtocol::passContentObjectToCallbacks(
}
void ByteStreamProductionProtocol::onInterest(Interest &interest) {
- TRANSPORT_LOGD("Received interest for %s",
- interest.getName().toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Received interest for " << interest.getName();
if (*on_interest_input_) {
on_interest_input_->operator()(*socket_->getInterface(), interest);
}
const std::shared_ptr<ContentObject> content_object =
- output_buffer_.find(interest);
+ output_buffer_.find(interest.getName());
if (content_object) {
if (*on_interest_satisfied_output_buffer_) {
diff --git a/libtransport/src/protocols/prod_protocol_rtc.cc b/libtransport/src/protocols/prod_protocol_rtc.cc
index 049752876..cdc882d81 100644
--- a/libtransport/src/protocols/prod_protocol_rtc.cc
+++ b/libtransport/src/protocols/prod_protocol_rtc.cc
@@ -25,15 +25,19 @@
namespace transport {
namespace protocol {
+using Format = core::Packet::Format;
+
RTCProductionProtocol::RTCProductionProtocol(
implementation::ProducerSocket *icn_socket)
: ProductionProtocol(icn_socket),
current_seg_(1),
produced_bytes_(0),
produced_packets_(0),
+ produced_fec_packets_(0),
max_packet_production_(1),
bytes_production_rate_(0),
packets_production_rate_(0),
+ fec_packets_production_rate_(0),
last_round_(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count()),
@@ -43,11 +47,17 @@ RTCProductionProtocol::RTCProductionProtocol(
on_consumer_in_sync_(nullptr) {
srand((unsigned int)time(NULL));
prod_label_ = rand() % 256;
+ cache_label_ = (prod_label_ + 1) % 256;
interests_queue_timer_ =
std::make_unique<asio::steady_timer>(portal_->getIoService());
round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
setOutputBufferSize(10000);
scheduleRoundTimer();
+
+ // FEC
+ using namespace std::placeholders;
+ enableFEC(std::bind(&RTCProductionProtocol::onFecPackets, this, _1),
+ std::bind(&RTCProductionProtocol::getBuffer, this, _1));
}
RTCProductionProtocol::~RTCProductionProtocol() {}
@@ -61,10 +71,19 @@ void RTCProductionProtocol::registerNamespaceWithNetwork(
switch (family) {
case AF_INET6:
- header_size_ = (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET6_TCP);
+ data_header_size_ =
+ signer_ && !making_manifest_
+ ? (uint32_t)Packet::getHeaderSizeFromFormat(
+ HF_INET6_TCP_AH, signer_->getSignatureFieldSize())
+ : (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET6_TCP);
+ ;
break;
case AF_INET:
- header_size_ = (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET_TCP);
+ data_header_size_ =
+ signer_ && !making_manifest_
+ ? (uint32_t)Packet::getHeaderSizeFromFormat(
+ HF_INET_TCP_AH, signer_->getSignatureFieldSize())
+ : (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET_TCP);
break;
default:
throw errors::RuntimeException("Unknown name format.");
@@ -90,16 +109,19 @@ void RTCProductionProtocol::updateStats() {
uint32_t prev_packets_production_rate = packets_production_rate_;
- bytes_production_rate_ = (uint32_t)ceil((double)produced_bytes_ * per_second);
- packets_production_rate_ = (uint32_t)ceil((double)produced_packets_ * per_second);
+ bytes_production_rate_ = ceil((double)produced_bytes_ * per_second);
+ packets_production_rate_ = ceil((double)produced_packets_ * per_second);
+ fec_packets_production_rate_ =
+ ceil((double)produced_fec_packets_ * per_second);
- TRANSPORT_LOGD("Updating production rate: produced_bytes_ = %u bps = %u",
- produced_bytes_, bytes_production_rate_);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Updating production rate: produced_bytes_ = " << produced_bytes_
+ << " bps = " << bytes_production_rate_;
// update the production rate as soon as it increases by 10% with respect to
// the last round
max_packet_production_ =
- produced_packets_ + (uint32_t)ceil((double)produced_packets_ * 0.1);
+ produced_packets_ + ceil((double)produced_packets_ * 0.1);
if (max_packet_production_ < rtc::WIN_MIN)
max_packet_production_ = rtc::WIN_MIN;
@@ -117,6 +139,7 @@ void RTCProductionProtocol::updateStats() {
produced_bytes_ = 0;
produced_packets_ = 0;
+ produced_fec_packets_ = 0;
last_round_ = now;
scheduleRoundTimer();
}
@@ -147,32 +170,34 @@ uint32_t RTCProductionProtocol::produceDatagram(
socket_->getSocketOption(interface::GeneralTransportOptions::DATA_PACKET_SIZE,
data_packet_size);
- if (TRANSPORT_EXPECT_FALSE((buffer_size + header_size_ +
+ if (TRANSPORT_EXPECT_FALSE((buffer_size + data_header_size_ +
rtc::DATA_HEADER_SIZE) > data_packet_size)) {
return 0;
}
auto content_object =
- core::PacketManager<>::getInstance().getPacket<ContentObject>();
+ core::PacketManager<>::getInstance().getPacket<ContentObject>(
+ signer_ ? Format::HF_INET6_TCP_AH : Format::HF_INET6_TCP,
+ signer_ ? signer_->getSignatureFieldSize() : 0);
// add rtc header to the payload
struct rtc::data_packet_t header;
content_object->appendPayload((const uint8_t *)&header,
rtc::DATA_HEADER_SIZE);
content_object->appendPayload(buffer->data(), buffer->length());
- std::shared_ptr<ContentObject> co = std::move(content_object);
-
// schedule actual sending on internal thread
- portal_->getIoService().dispatch(
- [this, content_object{std::move(co)}, content_name]() mutable {
- produceInternal(std::move(content_object), content_name);
- });
+ portal_->getIoService().dispatch([this,
+ content_object{std::move(content_object)},
+ content_name]() mutable {
+ produceInternal(std::move(content_object), content_name);
+ });
return 1;
}
void RTCProductionProtocol::produceInternal(
- std::shared_ptr<ContentObject> &&content_object, const Name &content_name) {
+ std::shared_ptr<ContentObject> &&content_object, const Name &content_name,
+ bool fec) {
// set rtc header
struct rtc::data_packet_t *data_pkt =
(struct rtc::data_packet_t *)content_object->getPayload()->data();
@@ -188,10 +213,19 @@ void RTCProductionProtocol::produceInternal(
content_object->setLifetime(500); // XXX this should be set by the APP
content_object->setPathLabel(prod_label_);
+ // sign packet
+ if (signer_) {
+ signer_->signPacket(content_object.get());
+ }
+
// update stats
- produced_bytes_ += (uint32_t)(
- content_object->headerSize() + content_object->payloadSize());
- produced_packets_++;
+ if (!fec) {
+ produced_bytes_ +=
+ content_object->headerSize() + content_object->payloadSize();
+ produced_packets_++;
+ } else {
+ produced_fec_packets_++;
+ }
if (produced_packets_ >= max_packet_production_) {
// in this case all the pending interests may be used to accomodate the
@@ -201,7 +235,14 @@ void RTCProductionProtocol::produceInternal(
updateStats();
}
- TRANSPORT_LOGD("Sending content object: %s", n.toString().c_str());
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Sending content object: " << n << ", is fec: " << fec;
+
+ // pass packet to FEC encoder
+ if (fec_encoder_ && !fec) {
+ fec_encoder_->onPacketProduced(
+ *content_object, content_object->headerSize() + rtc::DATA_HEADER_SIZE);
+ }
output_buffer_.insert(content_object);
@@ -210,7 +251,10 @@ void RTCProductionProtocol::produceInternal(
*content_object);
}
- portal_->sendContentObject(*content_object);
+ auto seq_it = seqs_map_.find(current_seg_);
+ if (seq_it != seqs_map_.end()) {
+ portal_->sendContentObject(*content_object);
+ }
if (*on_content_object_output_) {
on_content_object_output_->operator()(*socket_->getInterface(),
@@ -220,58 +264,84 @@ void RTCProductionProtocol::produceInternal(
// remove interests from the interest cache if it exists
removeFromInterestQueue(current_seg_);
+ // Update current segment
current_seg_ = (current_seg_ + 1) % rtc::MIN_PROBE_SEQ;
+
+ // Publish FEC packets if available
+ if (fec_encoder_ && !fec) {
+ while (!fec && pending_fec_packets_.size()) {
+ auto &co = pending_fec_packets_.front();
+ produceInternal(std::move(co), flow_name_, true);
+ pending_fec_packets_.pop();
+ }
+ }
}
void RTCProductionProtocol::onInterest(Interest &interest) {
- uint32_t interest_seg = interest.getName().getSuffix();
- uint32_t lifetime = interest.getLifetime();
+ if (*on_interest_input_) {
+ on_interest_input_->operator()(*socket_->getInterface(), interest);
+ }
+
+ auto suffix = interest.firstSuffix();
+ // numberOfSuffixes returns only the prefixes in the payalod
+ // we add + 1 to count anche the seq in the name
+ auto n_suffixes = interest.numberOfSuffixes() + 1;
+ Name name = interest.getName();
+ bool prev_consumer_state = consumer_in_sync_;
+
+ for (uint32_t i = 0; i < n_suffixes; i++) {
+ if (i > 0) {
+ name.setSuffix(*(suffix + (i - 1)));
+ }
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received interest " << name;
+ const std::shared_ptr<ContentObject> content_object =
+ output_buffer_.find(name);
+
+ if (content_object) {
+ if (*on_interest_satisfied_output_buffer_) {
+ on_interest_satisfied_output_buffer_->operator()(
+ *socket_->getInterface(), interest);
+ }
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(),
+ *content_object);
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Send content %u (onInterest) " << content_object->getName();
+ content_object->setPathLabel(cache_label_);
+ portal_->sendContentObject(*content_object);
+ } else {
+ if (*on_interest_process_) {
+ on_interest_process_->operator()(*socket_->getInterface(), interest);
+ }
+ processInterest(name.getSuffix(), interest.getLifetime());
+ }
+ }
+
+ if (prev_consumer_state != consumer_in_sync_ && consumer_in_sync_)
+ on_consumer_in_sync_(*socket_->getInterface(), interest);
+}
+
+void RTCProductionProtocol::processInterest(uint32_t interest_seg,
+ uint32_t lifetime) {
if (interest_seg == 0) {
// first packet from the consumer, reset sync state
consumer_in_sync_ = false;
}
- if (*on_interest_input_) {
- on_interest_input_->operator()(*socket_->getInterface(), interest);
- }
-
uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
if (interest_seg > rtc::MIN_PROBE_SEQ) {
- TRANSPORT_LOGD("received probe %u", interest_seg);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received probe " << interest_seg;
sendNack(interest_seg);
return;
}
- TRANSPORT_LOGD("received interest %u", interest_seg);
-
- const std::shared_ptr<ContentObject> content_object =
- output_buffer_.find(interest);
-
- if (content_object) {
- if (*on_interest_satisfied_output_buffer_) {
- on_interest_satisfied_output_buffer_->operator()(*socket_->getInterface(),
- interest);
- }
-
- if (*on_content_object_output_) {
- on_content_object_output_->operator()(*socket_->getInterface(),
- *content_object);
- }
-
- TRANSPORT_LOGD("Send content %u (onInterest)",
- content_object->getName().getSuffix());
- portal_->sendContentObject(*content_object);
- return;
- } else {
- if (*on_interest_process_) {
- on_interest_process_->operator()(*socket_->getInterface(), interest);
- }
- }
-
// if the production rate 0 use delayed nacks
if (allow_delayed_nacks_ && interest_seg >= current_seg_) {
uint64_t next_timer = ~0;
@@ -310,7 +380,8 @@ void RTCProductionProtocol::onInterest(Interest &interest) {
(double)((double)((double)lifetime *
rtc::INTEREST_LIFETIME_REDUCTION_FACTOR /
rtc::MILLI_IN_A_SEC) *
- (double)packets_production_rate_));
+ (double)(packets_production_rate_ +
+ fec_packets_production_rate_)));
if (interest_seg < current_seg_ || interest_seg > (max_gap + current_seg_)) {
sendNack(interest_seg);
@@ -318,14 +389,14 @@ void RTCProductionProtocol::onInterest(Interest &interest) {
if (!consumer_in_sync_ && on_consumer_in_sync_) {
// we consider the remote consumer to be in sync as soon as it covers 70%
// of the production window with interests
- uint32_t perc = (uint32_t)ceil((double)max_gap * 0.7);
+ uint32_t perc = ceil((double)max_gap * 0.7);
if (interest_seg > (perc + current_seg_)) {
consumer_in_sync_ = true;
- on_consumer_in_sync_(*socket_->getInterface(), interest);
+ // on_consumer_in_sync_(*socket_->getInterface(), interest);
}
}
- uint64_t expiration =(uint32_t)(
- now + floor((double)lifetime * rtc::INTEREST_LIFETIME_REDUCTION_FACTOR));
+ uint64_t expiration =
+ now + floor((double)lifetime * rtc::INTEREST_LIFETIME_REDUCTION_FACTOR);
addToInterestQueue(interest_seg, expiration);
}
}
@@ -377,7 +448,7 @@ void RTCProductionProtocol::sendNacksForPendingInterests() {
uint32_t packet_gap = 100000; // set it to a high value (100sec)
if (packets_production_rate_ != 0)
- packet_gap = (uint32_t)ceil(rtc::MILLI_IN_A_SEC / (double)packets_production_rate_);
+ packet_gap = ceil(rtc::MILLI_IN_A_SEC / (double)packets_production_rate_);
uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
@@ -441,7 +512,9 @@ void RTCProductionProtocol::interestQueueTimer() {
}
void RTCProductionProtocol::sendNack(uint32_t sequence) {
- auto nack = core::PacketManager<>::getInstance().getPacket<ContentObject>();
+ auto nack = core::PacketManager<>::getInstance().getPacket<ContentObject>(
+ signer_ ? Format::HF_INET6_TCP_AH : Format::HF_INET6_TCP,
+ signer_ ? signer_->getSignatureFieldSize() : 0);
uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
@@ -460,6 +533,10 @@ void RTCProductionProtocol::sendNack(uint32_t sequence) {
nack->setLifetime(0);
nack->setPathLabel(prod_label_);
+ if (signer_) {
+ signer_->signPacket(nack.get());
+ }
+
if (!consumer_in_sync_ && on_consumer_in_sync_ &&
sequence < rtc::MIN_PROBE_SEQ && sequence > next_packet) {
consumer_in_sync_ = true;
@@ -472,10 +549,39 @@ void RTCProductionProtocol::sendNack(uint32_t sequence) {
on_content_object_output_->operator()(*socket_->getInterface(), *nack);
}
- TRANSPORT_LOGD("Send nack %u", sequence);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send nack " << sequence;
portal_->sendContentObject(*nack);
}
+void RTCProductionProtocol::onFecPackets(
+ std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Produced " << packets.size() << " FEC packets";
+ for (auto &packet : packets) {
+ auto content_object =
+ std::static_pointer_cast<ContentObject>(packet.second);
+ content_object->prepend(content_object->headerSize() +
+ rtc::DATA_HEADER_SIZE);
+ pending_fec_packets_.push(std::move(content_object));
+ }
+}
+
+fec::buffer RTCProductionProtocol::getBuffer(std::size_t size) {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Asked buffer for FEC symbol of size " << size;
+ auto ret = core::PacketManager<>::getInstance().getPacket<ContentObject>(
+ signer_ ? Format::HF_INET6_TCP_AH : Format::HF_INET6_TCP,
+ signer_ ? signer_->getSignatureFieldSize() : 0);
+ ret->updateLength(rtc::DATA_HEADER_SIZE + size);
+ ret->append(rtc::DATA_HEADER_SIZE + size);
+ ret->trimStart(ret->headerSize() + rtc::DATA_HEADER_SIZE);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Responding with buffer of length " << ret->length();
+ assert(ret->length() >= size);
+
+ return ret;
+}
+
} // namespace protocol
} // end namespace transport
diff --git a/libtransport/src/protocols/prod_protocol_rtc.h b/libtransport/src/protocols/prod_protocol_rtc.h
index f3584f74a..96ad5673d 100644
--- a/libtransport/src/protocols/prod_protocol_rtc.h
+++ b/libtransport/src/protocols/prod_protocol_rtc.h
@@ -60,8 +60,9 @@ class RTCProductionProtocol : public ProductionProtocol {
// packet handlers
void onInterest(Interest &interest) override;
void onError(std::error_code ec) override;
+ void processInterest(uint32_t interest_seg, uint32_t lifetime);
void produceInternal(std::shared_ptr<ContentObject> &&content_object,
- const Name &content_name);
+ const Name &content_name, bool fec = false);
void sendNack(uint32_t sequence);
// stats
@@ -75,20 +76,27 @@ class RTCProductionProtocol : public ProductionProtocol {
void scheduleQueueTimer(uint64_t wait);
void interestQueueTimer();
+ // FEC functions
+ void onFecPackets(std::vector<std::pair<uint32_t, fec::buffer>> &packets);
+ fec::buffer getBuffer(std::size_t size);
+
core::Name flow_name_;
- uint32_t current_seg_; // seq id of the next packet produced
- uint32_t prod_label_; // path lable of the producer
- uint16_t header_size_; // hicn header size
+ uint32_t current_seg_; // seq id of the next packet produced
+ uint32_t prod_label_; // path lable of the producer
+ uint32_t cache_label_; // path lable for content from the producer cache
+ uint16_t data_header_size_; // hicn data header size
- uint32_t produced_bytes_; // bytes produced in the last round
- uint32_t produced_packets_; // packet produed in the last round
+ uint32_t produced_bytes_; // bytes produced in the last round
+ uint32_t produced_packets_; // packet produed in the last round
+ uint32_t produced_fec_packets_; // fec packets produced last round
uint32_t max_packet_production_; // never exceed this number of packets
// without update stats
- uint32_t bytes_production_rate_; // bytes per sec
- uint32_t packets_production_rate_; // pps
+ uint32_t bytes_production_rate_; // bytes per sec
+ uint32_t packets_production_rate_; // pps
+ uint32_t fec_packets_production_rate_; // pps
std::unique_ptr<asio::steady_timer> round_timer_;
uint64_t last_round_;
@@ -120,6 +128,9 @@ class RTCProductionProtocol : public ProductionProtocol {
// impossible to know the state of the consumers so it should not be used.
bool consumer_in_sync_;
interface::ProducerInterestCallback on_consumer_in_sync_;
+
+ // Save FEC packets here before sending them
+ std::queue<ContentObject::Ptr> pending_fec_packets_;
};
} // namespace protocol
diff --git a/libtransport/src/protocols/production_protocol.cc b/libtransport/src/protocols/production_protocol.cc
index 8addf52d1..6b317d47d 100644
--- a/libtransport/src/protocols/production_protocol.cc
+++ b/libtransport/src/protocols/production_protocol.cc
@@ -26,6 +26,7 @@ ProductionProtocol::ProductionProtocol(
implementation::ProducerSocket *icn_socket)
: socket_(icn_socket),
is_running_(false),
+ fec_encoder_(nullptr),
on_interest_input_(VOID_HANDLER),
on_interest_dropped_input_buffer_(VOID_HANDLER),
on_interest_inserted_input_buffer_(VOID_HANDLER),
@@ -36,7 +37,8 @@ ProductionProtocol::ProductionProtocol(
on_content_object_in_output_buffer_(VOID_HANDLER),
on_content_object_output_(VOID_HANDLER),
on_content_object_evicted_from_output_buffer_(VOID_HANDLER),
- on_content_produced_(VOID_HANDLER) {
+ on_content_produced_(VOID_HANDLER),
+ fec_type_(fec::FECType::UNKNOWN) {
socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal_);
// TODO add statistics for producer
// socket_->getSocketOption(OtherOptions::STATISTICS, &stats_);
@@ -75,6 +77,9 @@ int ProductionProtocol::start() {
&on_content_produced_);
socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
+ socket_->getSocketOption(GeneralTransportOptions::SIGNER, signer_);
+ socket_->getSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
+ making_manifest_);
bool first = true;
diff --git a/libtransport/src/protocols/production_protocol.h b/libtransport/src/protocols/production_protocol.h
index 780972321..7366311eb 100644
--- a/libtransport/src/protocols/production_protocol.h
+++ b/libtransport/src/protocols/production_protocol.h
@@ -20,6 +20,8 @@
#include <hicn/transport/interfaces/statistics.h>
#include <hicn/transport/utils/object_pool.h>
#include <implementation/socket.h>
+#include <protocols/fec_base.h>
+#include <protocols/fec_utils.h>
#include <utils/content_store.h>
#include <atomic>
@@ -67,6 +69,27 @@ class ProductionProtocol : public Portal::ProducerCallback {
virtual void onInterest(core::Interest &i) override = 0;
virtual void onError(std::error_code ec) override{};
+ template <typename FECHandler, typename AllocatorHandler>
+ void enableFEC(FECHandler &&fec_handler,
+ AllocatorHandler &&allocator_handler) {
+ if (!fec_encoder_) {
+ // Try to get FEC from environment
+ if (const char *fec_str = std::getenv("TRANSPORT_FEC_TYPE")) {
+ LOG(INFO) << "Using FEC " << fec_str;
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_str);
+ }
+
+ if (fec_type_ == fec::FECType::UNKNOWN) {
+ return;
+ }
+
+ fec_encoder_ = fec::FECUtils::getEncoder(fec_type_, 1);
+ fec_encoder_->setFECCallback(std::forward<FECHandler>(fec_handler));
+ fec_encoder_->setBufferCallback(
+ std::forward<AllocatorHandler>(allocator_handler));
+ }
+ }
+
protected:
implementation::ProducerSocket *socket_;
@@ -78,6 +101,7 @@ class ProductionProtocol : public Portal::ProducerCallback {
std::shared_ptr<Portal> portal_;
std::atomic<bool> is_running_;
interface::ProductionStatistics *stats_;
+ std::unique_ptr<fec::ProducerFEC> fec_encoder_;
// Callbacks
interface::ProducerInterestCallback *on_interest_input_;
@@ -101,7 +125,12 @@ class ProductionProtocol : public Portal::ProducerCallback {
// List ot routes served by current producer protocol
std::list<Prefix> served_namespaces_;
+ // Signature and manifest
+ std::shared_ptr<auth::Signer> signer_;
+ bool making_manifest_;
+
bool is_async_;
+ fec::FECType fec_type_;
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/protocol.cc b/libtransport/src/protocols/protocol.cc
deleted file mode 100644
index 451fef80d..000000000
--- a/libtransport/src/protocols/protocol.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/interfaces/socket_consumer.h>
-#include <implementation/socket_consumer.h>
-#include <protocols/protocol.h>
-
-namespace transport {
-
-namespace protocol {
-
-using namespace interface;
-
-TransportProtocol::TransportProtocol(implementation::ConsumerSocket *icn_socket,
- Reassembly *reassembly_protocol)
- : socket_(icn_socket),
- reassembly_protocol_(reassembly_protocol),
- index_manager_(
- std::make_unique<IndexManager>(socket_, this, reassembly_protocol)),
- is_running_(false),
- is_first_(false),
- on_interest_retransmission_(VOID_HANDLER),
- on_interest_output_(VOID_HANDLER),
- on_interest_timeout_(VOID_HANDLER),
- on_interest_satisfied_(VOID_HANDLER),
- on_content_object_input_(VOID_HANDLER),
- on_content_object_verification_(VOID_HANDLER),
- stats_summary_(VOID_HANDLER),
- verification_failed_callback_(VOID_HANDLER),
- on_payload_(VOID_HANDLER) {
- socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal_);
- socket_->getSocketOption(OtherOptions::STATISTICS, &stats_);
-}
-
-int TransportProtocol::start() {
- // If the protocol is already running, return otherwise set as running
- if (is_running_) return -1;
-
- // Get all callbacks references before starting
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_RETRANSMISSION,
- &on_interest_retransmission_);
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_OUTPUT,
- &on_interest_output_);
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_EXPIRED,
- &on_interest_timeout_);
- socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_SATISFIED,
- &on_interest_satisfied_);
- socket_->getSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
- &on_content_object_input_);
- socket_->getSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY,
- &on_content_object_verification_);
- socket_->getSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY,
- &stats_summary_);
- socket_->getSocketOption(ConsumerCallbacksOptions::VERIFICATION_FAILED,
- &verification_failed_callback_);
- socket_->getSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
- &on_payload_);
- socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
-
- // Set it is the first time we schedule an interest
- is_first_ = true;
-
- // Reset the protocol state machine
- reset();
- // Schedule next interests
- scheduleNextInterests();
-
- is_first_ = false;
-
- // Set the protocol as running
- is_running_ = true;
-
- if (!is_async_) {
- // Start Event loop
- portal_->runEventsLoop();
-
- // Not running anymore
- is_running_ = false;
- }
-
- return 0;
-}
-
-void TransportProtocol::stop() {
- is_running_ = false;
-
- if (!is_async_) {
- portal_->stopEventsLoop();
- } else {
- portal_->clear();
- }
-}
-
-void TransportProtocol::resume() {
- if (is_running_) return;
-
- is_running_ = true;
-
- scheduleNextInterests();
-
- portal_->runEventsLoop();
-
- is_running_ = false;
-}
-
-void TransportProtocol::onContentReassembled(std::error_code ec) {
- stop();
-
- if (!on_payload_) {
- throw errors::RuntimeException(
- "The read callback must be installed in the transport before "
- "starting "
- "the content retrieval.");
- }
-
- if (!ec) {
- on_payload_->readSuccess(stats_->getBytesRecv());
- } else {
- on_payload_->readError(ec);
- }
-}
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/protocol.h b/libtransport/src/protocols/protocol.h
deleted file mode 100644
index 73a0a2c64..000000000
--- a/libtransport/src/protocols/protocol.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/interfaces/callbacks.h>
-#include <hicn/transport/interfaces/socket_consumer.h>
-#include <hicn/transport/interfaces/statistics.h>
-#include <hicn/transport/utils/object_pool.h>
-#include <implementation/socket.h>
-#include <protocols/data_processing_events.h>
-#include <protocols/indexer.h>
-#include <protocols/packet_manager.h>
-#include <protocols/reassembly.h>
-
-#include <atomic>
-
-namespace transport {
-
-namespace protocol {
-
-using namespace core;
-
-class IndexVerificationManager;
-
-using ReadCallback = interface::ConsumerSocket::ReadCallback;
-
-class TransportProtocolCallback {
- virtual void onContentObject(const core::Interest &interest,
- const core::ContentObject &content_object) = 0;
- virtual void onTimeout(const core::Interest &interest) = 0;
-};
-
-class TransportProtocol : public implementation::BasePortal::ConsumerCallback,
- public PacketManager<Interest>,
- public ContentObjectProcessingEventCallback {
- static constexpr std::size_t interest_pool_size = 4096;
-
- friend class ManifestIndexManager;
-
- public:
- TransportProtocol(implementation::ConsumerSocket *icn_socket,
- Reassembly *reassembly_protocol);
-
- virtual ~TransportProtocol() = default;
-
- TRANSPORT_ALWAYS_INLINE bool isRunning() { return is_running_; }
-
- virtual int start();
-
- virtual void stop();
-
- virtual void resume();
-
- virtual bool verifyKeyPackets() = 0;
-
- virtual void scheduleNextInterests() = 0;
-
- // Events generated by the indexing
- virtual void onContentReassembled(std::error_code ec);
- virtual void onPacketDropped(
- Interest::Ptr &&interest,
- ContentObject::Ptr &&content_object) override = 0;
- virtual void onReassemblyFailed(std::uint32_t missing_segment) override = 0;
-
- protected:
- // Consumer Callback
- virtual void reset() = 0;
- virtual void onContentObject(Interest::Ptr &&i,
- ContentObject::Ptr &&c) override = 0;
- virtual void onTimeout(Interest::Ptr &&i) override = 0;
- virtual void onError(std::error_code ec) override {}
-
- protected:
- implementation::ConsumerSocket *socket_;
- std::unique_ptr<Reassembly> reassembly_protocol_;
- std::unique_ptr<IndexManager> index_manager_;
- std::shared_ptr<implementation::BasePortal> portal_;
- std::atomic<bool> is_running_;
- // True if it si the first time we schedule an interest
- std::atomic<bool> is_first_;
- interface::TransportStatistics *stats_;
-
- // Callbacks
- interface::ConsumerInterestCallback *on_interest_retransmission_;
- interface::ConsumerInterestCallback *on_interest_output_;
- interface::ConsumerInterestCallback *on_interest_timeout_;
- interface::ConsumerInterestCallback *on_interest_satisfied_;
- interface::ConsumerContentObjectCallback *on_content_object_input_;
- interface::ConsumerContentObjectVerificationCallback
- *on_content_object_verification_;
- interface::ConsumerContentObjectCallback *on_content_object_;
- interface::ConsumerTimerCallback *stats_summary_;
- interface::ConsumerContentObjectVerificationFailedCallback
- *verification_failed_callback_;
- ReadCallback *on_payload_;
-
- bool is_async_;
-};
-
-} // end namespace protocol
-} // end namespace transport
diff --git a/libtransport/src/protocols/raaqm.cc b/libtransport/src/protocols/raaqm.cc
index bc8500227..1247af400 100644
--- a/libtransport/src/protocols/raaqm.cc
+++ b/libtransport/src/protocols/raaqm.cc
@@ -17,7 +17,7 @@
#include <hicn/transport/interfaces/socket_consumer.h>
#include <implementation/socket_consumer.h>
#include <protocols/errors.h>
-#include <protocols/indexer.h>
+#include <protocols/index_manager_bytestream.h>
#include <protocols/raaqm.h>
#include <cstdlib>
@@ -31,7 +31,8 @@ using namespace interface;
RaaqmTransportProtocol::RaaqmTransportProtocol(
implementation::ConsumerSocket *icn_socket)
- : TransportProtocol(icn_socket, new ByteStreamReassembly(icn_socket, this)),
+ : TransportProtocol(icn_socket, new IndexManager(icn_socket, this),
+ new ByteStreamReassembly(icn_socket, this)),
current_window_size_(1),
interests_in_flight_(0),
cur_path_(nullptr),
@@ -47,11 +48,34 @@ RaaqmTransportProtocol::~RaaqmTransportProtocol() {
}
}
-int RaaqmTransportProtocol::start() {
+void RaaqmTransportProtocol::reset() {
+ // Set first segment to retrieve
+ TransportProtocol::reset();
+ core::Name *name;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
+ indexer_verifier_->setFirstSuffix(name->getSuffix());
+ std::queue<uint32_t> empty;
+ std::swap(interest_to_retransmit_, empty);
+ stats_->reset();
+
+ // Reset protocol variables
+ interests_in_flight_ = 0;
+ t0_ = utils::SteadyClock::now();
+
+ // Optionally reset congestion window
+ bool reset_window;
+ socket_->getSocketOption(RaaqmTransportOptions::PER_SESSION_CWINDOW_RESET,
+ reset_window);
+ if (reset_window) {
+ current_window_size_ = 1;
+ }
+
+ // Reset rate estimator
if (rate_estimator_) {
rate_estimator_->onStart();
}
+ // If not cur_path exists, create one
if (!cur_path_) {
// RAAQM
double drop_factor;
@@ -94,37 +118,6 @@ int RaaqmTransportProtocol::start() {
cur_path_ = cur_path.get();
path_table_[default_values::path_id] = std::move(cur_path);
}
-
- portal_->setConsumerCallback(this);
- return TransportProtocol::start();
-}
-
-void RaaqmTransportProtocol::resume() { return TransportProtocol::resume(); }
-
-void RaaqmTransportProtocol::reset() {
- // Set first segment to retrieve
- core::Name *name;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
- index_manager_->reset();
- index_manager_->setFirstSuffix(name->getSuffix());
- std::queue<Interest::Ptr> empty;
- std::swap(interest_to_retransmit_, empty);
- stats_->reset();
-
- // Reset reassembly component
- reassembly_protocol_->reInitialize();
-
- // Reset protocol variables
- interests_in_flight_ = 0;
- t0_ = utils::SteadyClock::now();
-
- // Optionally reset congestion window
- bool reset_window;
- socket_->getSocketOption(RaaqmTransportOptions::PER_SESSION_CWINDOW_RESET,
- reset_window);
- if (reset_window) {
- current_window_size_ = 1;
- }
}
void RaaqmTransportProtocol::increaseWindow() {
@@ -194,9 +187,8 @@ void RaaqmTransportProtocol::init() {
lte_delay_ = 15000;
if (!is) {
- TRANSPORT_LOGW(
- "WARNING: RAAQM parameters not found at %s, set default values",
- RAAQM_CONFIG_PATH);
+ LOG(WARNING) << "RAAQM parameters not found at " << RAAQM_CONFIG_PATH
+ << ", set default values";
return;
}
@@ -322,12 +314,9 @@ void RaaqmTransportProtocol::init() {
is.close();
}
-void RaaqmTransportProtocol::onContentObject(Interest &interest,
- ContentObject &content_object) {
- // Check whether makes sense to continue
- if (TRANSPORT_EXPECT_FALSE(!is_running_)) {
- return;
- }
+void RaaqmTransportProtocol::onContentObjectReceived(
+ Interest &interest, ContentObject &content_object, std::error_code &ec) {
+ uint32_t incremental_suffix = content_object.getName().getSuffix();
// Call application-defined callbacks
if (*on_content_object_input_) {
@@ -338,18 +327,12 @@ void RaaqmTransportProtocol::onContentObject(Interest &interest,
(*on_interest_satisfied_)(*socket_->getInterface(), interest);
}
+ ec = make_error_code(protocol_error::success);
+
if (content_object.getPayloadType() == PayloadType::DATA) {
stats_->updateBytesRecv(content_object.payloadSize());
}
- onContentSegment(interest, content_object);
- scheduleNextInterests();
-}
-
-void RaaqmTransportProtocol::onContentSegment(Interest &interest,
- ContentObject &content_object) {
- uint32_t incremental_suffix = content_object.getName().getSuffix();
-
// Decrease in-flight interests
interests_in_flight_--;
@@ -358,11 +341,13 @@ void RaaqmTransportProtocol::onContentSegment(Interest &interest,
afterContentReception(interest, content_object);
}
- index_manager_->onContentObject(interest, content_object);
+ // Schedule next interests
+ scheduleNextInterests();
}
void RaaqmTransportProtocol::onPacketDropped(Interest &interest,
- ContentObject &content_object) {
+ ContentObject &content_object,
+ const std::error_code &reason) {
uint32_t max_rtx = 0;
socket_->getSocketOption(GeneralTransportOptions::MAX_INTEREST_RETX, max_rtx);
@@ -380,16 +365,15 @@ void RaaqmTransportProtocol::onPacketDropped(Interest &interest,
(*on_interest_output_)(*socket_->getInterface(), interest);
}
- if (!is_running_) {
+ if (!isRunning()) {
return;
}
interest_retransmissions_[segment & mask]++;
- interest_to_retransmit_.push(interest.shared_from_this());
+ interest_to_retransmit_.push(segment);
} else {
- TRANSPORT_LOGE(
- "Stop: received not trusted packet %llu times",
- (unsigned long long)interest_retransmissions_[segment & mask]);
+ LOG(ERROR) << "Stop: received not trusted packet "
+ << interest_retransmissions_[segment & mask] << " times";
onContentReassembled(
make_error_code(protocol_error::max_retransmissions_error));
}
@@ -399,23 +383,25 @@ void RaaqmTransportProtocol::onReassemblyFailed(std::uint32_t missing_segment) {
}
-void RaaqmTransportProtocol::onTimeout(Interest::Ptr &&interest) {
- checkForStalePaths();
-
- const Name &n = interest->getName();
-
- TRANSPORT_LOGW("Timeout on content %s", n.toString().c_str());
+void RaaqmTransportProtocol::sendInterest(
+ const Name &interest_name,
+ std::array<uint32_t, MAX_AGGREGATED_INTEREST> *additional_suffixes,
+ uint32_t len) {
+ interests_in_flight_++;
+ interest_retransmissions_[interest_name.getSuffix() & mask]++;
+ TransportProtocol::sendInterest(interest_name, additional_suffixes, len);
+}
- if (TRANSPORT_EXPECT_FALSE(!is_running_)) {
- return;
- }
+void RaaqmTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
+ const Name &n) {
+ checkForStalePaths();
interests_in_flight_--;
uint64_t segment = n.getSuffix();
// Do not retransmit interests asking contents that do not exist.
- if (segment > index_manager_->getFinalSuffix()) {
+ if (segment > indexer_verifier_->getFinalSuffix()) {
return;
}
@@ -436,32 +422,34 @@ void RaaqmTransportProtocol::onTimeout(Interest::Ptr &&interest) {
(*on_interest_retransmission_)(*socket_->getInterface(), *interest);
}
- if (!is_running_) {
+ if (!isRunning()) {
return;
}
- interest_retransmissions_[segment & mask]++;
- interest_to_retransmit_.push(std::move(interest));
-
+ interest_to_retransmit_.push(segment);
scheduleNextInterests();
} else {
- TRANSPORT_LOGE("Stop: reached max retx limit.");
+ LOG(ERROR) << "Stop: reached max retx limit.";
onContentReassembled(std::make_error_code(std::errc(std::errc::io_error)));
}
}
void RaaqmTransportProtocol::scheduleNextInterests() {
- bool cancel = (!is_running_ && !is_first_) || !schedule_interests_;
+ bool cancel = (!isRunning() && !is_first_) || !schedule_interests_;
if (TRANSPORT_EXPECT_FALSE(cancel)) {
schedule_interests_ = true;
return;
}
+ core::Name *name;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
+
if (TRANSPORT_EXPECT_FALSE(interests_in_flight_ >= current_window_size_ &&
interest_to_retransmit_.size() > 0)) {
// send at least one interest if there are retransmissions to perform and
// there is no space left in the window
- sendInterest(std::move(interest_to_retransmit_.front()));
+ auto suffix = interest_to_retransmit_.front();
+ sendInterest(name->setSuffix(suffix));
interest_to_retransmit_.pop();
}
@@ -470,55 +458,25 @@ void RaaqmTransportProtocol::scheduleNextInterests() {
// Send the interest needed for filling the window
while (interests_in_flight_ < current_window_size_) {
if (interest_to_retransmit_.size() > 0) {
- sendInterest(std::move(interest_to_retransmit_.front()));
+ auto suffix = interest_to_retransmit_.front();
+ sendInterest(name->setSuffix(suffix));
interest_to_retransmit_.pop();
} else {
- if (TRANSPORT_EXPECT_FALSE(!is_running_ && !is_first_)) {
- TRANSPORT_LOGI("Adios");
+ if (TRANSPORT_EXPECT_FALSE(!isRunning() && !is_first_)) {
break;
}
- index = index_manager_->getNextSuffix();
+ index = indexer_verifier_->getNextSuffix();
if (index == IndexManager::invalid_index) {
break;
}
- sendInterest(index);
+ interest_retransmissions_[index & mask] = ~0;
+ sendInterest(name->setSuffix(index));
}
}
}
-void RaaqmTransportProtocol::sendInterest(std::uint64_t next_suffix) {
- auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
- core::Name *name;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
- name->setSuffix((uint32_t)next_suffix);
- interest->setName(*name);
-
- uint32_t interest_lifetime;
- socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
- interest_lifetime);
- interest->setLifetime(interest_lifetime);
-
- if (*on_interest_output_) {
- on_interest_output_->operator()(*socket_->getInterface(), *interest);
- }
- // This is set to ~0 so that the next interest_retransmissions_ + 1,
- // performed by sendInterest, will result in 0
- interest_retransmissions_[next_suffix & mask] = ~0;
- interest_timepoints_[next_suffix & mask] = utils::SteadyClock::now();
-
- sendInterest(std::move(interest));
-}
-
-void RaaqmTransportProtocol::sendInterest(Interest::Ptr &&interest) {
- interests_in_flight_++;
- interest_retransmissions_[interest->getName().getSuffix() & mask]++;
-
- TRANSPORT_LOGD("Send interest %s", interest->getName().toString().c_str());
- portal_->sendInterest(std::move(interest));
-}
-
void RaaqmTransportProtocol::onContentReassembled(std::error_code ec) {
rate_estimator_->onDownloadFinished();
TransportProtocol::onContentReassembled(ec);
diff --git a/libtransport/src/protocols/raaqm.h b/libtransport/src/protocols/raaqm.h
index be477d39f..ffbb30d3a 100644
--- a/libtransport/src/protocols/raaqm.h
+++ b/libtransport/src/protocols/raaqm.h
@@ -32,13 +32,12 @@ namespace protocol {
class RaaqmTransportProtocol : public TransportProtocol,
public CWindowProtocol {
public:
- RaaqmTransportProtocol(implementation::ConsumerSocket *icnet_socket);
+ RaaqmTransportProtocol(implementation::ConsumerSocket *icn_socket);
~RaaqmTransportProtocol();
- int start() override;
-
- void resume() override;
+ using TransportProtocol::start;
+ using TransportProtocol::stop;
void reset() override;
@@ -62,35 +61,24 @@ class RaaqmTransportProtocol : public TransportProtocol,
private:
void init();
- void onContentObject(Interest &i, ContentObject &c) override;
-
- void onContentSegment(Interest &interest, ContentObject &content_object);
-
- void onPacketDropped(Interest &interest,
- ContentObject &content_object) override;
-
+ void onContentObjectReceived(Interest &i, ContentObject &c,
+ std::error_code &ec) override;
+ void onPacketDropped(Interest &interest, ContentObject &content_object,
+ const std::error_code &reason) override;
void onReassemblyFailed(std::uint32_t missing_segment) override;
-
- void onTimeout(Interest::Ptr &&i) override;
-
+ void onInterestTimeout(Interest::Ptr &i, const Name &n) override;
virtual void scheduleNextInterests() override;
-
- void sendInterest(std::uint64_t next_suffix);
-
- void sendInterest(Interest::Ptr &&interest);
+ void sendInterest(const Name &interest_name,
+ std::array<uint32_t, MAX_AGGREGATED_INTEREST>
+ *additional_suffixes = nullptr,
+ uint32_t len = 0) override;
void onContentReassembled(std::error_code ec) override;
-
void updateRtt(uint64_t segment);
-
void RAAQM();
-
void updatePathTable(const ContentObject &content_object);
-
void checkDropProbability();
-
void checkForStalePaths();
-
void printRtt();
protected:
@@ -100,7 +88,7 @@ class RaaqmTransportProtocol : public TransportProtocol,
uint64_t interests_in_flight_;
std::array<std::uint32_t, buffer_size> interest_retransmissions_;
std::array<utils::TimePoint, buffer_size> interest_timepoints_;
- std::queue<Interest::Ptr> interest_to_retransmit_;
+ std::queue<uint32_t> interest_to_retransmit_;
private:
/**
diff --git a/libtransport/src/protocols/rate_estimation.cc b/libtransport/src/protocols/rate_estimation.cc
index 5ca925760..2337e18be 100644
--- a/libtransport/src/protocols/rate_estimation.cc
+++ b/libtransport/src/protocols/rate_estimation.cc
@@ -13,8 +13,8 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
-#include <hicn/transport/utils/log.h>
#include <protocols/rate_estimation.h>
#include <thread>
@@ -115,12 +115,12 @@ void InterRttEstimator::onRttUpdate(double rtt) {
if (!thread_is_running_) {
my_th_ = (pthread_t *)malloc(sizeof(pthread_t));
if (!my_th_) {
- TRANSPORT_LOGE("Error allocating thread.");
+ LOG(ERROR) << "Error allocating thread.";
my_th_ = NULL;
}
if (/*int err = */ pthread_create(my_th_, NULL, transport::protocol::Timer,
(void *)this)) {
- TRANSPORT_LOGE("Error creating the thread");
+ LOG(ERROR) << "Error creating the thread";
my_th_ = NULL;
}
thread_is_running_ = true;
diff --git a/libtransport/src/protocols/reassembly.cc b/libtransport/src/protocols/reassembly.cc
index 0e59832dc..ce24fce1b 100644
--- a/libtransport/src/protocols/reassembly.cc
+++ b/libtransport/src/protocols/reassembly.cc
@@ -31,7 +31,7 @@ void Reassembly::notifyApplication() {
interface::ConsumerCallbacksOptions::READ_CALLBACK, &read_callback);
if (TRANSPORT_EXPECT_FALSE(!read_callback)) {
- TRANSPORT_LOGE("Read callback not installed!");
+ LOG(ERROR) << "Read callback not installed!";
return;
}
diff --git a/libtransport/src/protocols/reassembly.h b/libtransport/src/protocols/reassembly.h
index 385122c53..e072ad123 100644
--- a/libtransport/src/protocols/reassembly.h
+++ b/libtransport/src/protocols/reassembly.h
@@ -46,19 +46,48 @@ class Reassembly {
virtual ~Reassembly() = default;
+ /**
+ * Hanle reassembly of content object.
+ */
virtual void reassemble(core::ContentObject &content_object) = 0;
+
+ /**
+ * Hanle reassembly of content object.
+ */
+ virtual void reassemble(utils::MemBuf &buffer, uint32_t suffix) = 0;
+
+ /**
+ * Handle reassembly of manifest
+ */
virtual void reassemble(
std::unique_ptr<core::ContentObjectManifest> &&manifest) = 0;
+
+ /**
+ * Reset reassembler for new round
+ */
virtual void reInitialize() = 0;
- virtual void setIndexer(Indexer *indexer) { index_manager_ = indexer; }
+
+ /**
+ * Use indexer to get next segments to reassembly
+ */
+ virtual void setIndexer(Indexer *indexer) { indexer_verifier_ = indexer; }
+
+ /**
+ * Decide if it is required to pass to application buffers whose verification
+ * has been delayed (e.g. because the manifest is missing). False by default.
+ */
+ virtual bool reassembleUnverified() { return false; }
protected:
+ /**
+ * Notify application there is data to read.
+ */
virtual void notifyApplication();
protected:
implementation::ConsumerSocket *reassembly_consumer_socket_;
TransportProtocol *transport_protocol_;
- Indexer *index_manager_;
+ Indexer *indexer_verifier_;
std::unique_ptr<utils::MemBuf> read_buffer_;
};
diff --git a/libtransport/src/protocols/rtc.cc b/libtransport/src/protocols/rtc.cc
deleted file mode 100644
index a01b8daa5..000000000
--- a/libtransport/src/protocols/rtc.cc
+++ /dev/null
@@ -1,984 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/interfaces/socket_consumer.h>
-#include <implementation/socket_consumer.h>
-#include <math.h>
-#include <protocols/rtc.h>
-
-#include <random>
-
-namespace transport {
-
-namespace protocol {
-
-using namespace interface;
-
-RTCTransportProtocol::RTCTransportProtocol(
- implementation::ConsumerSocket *icn_socket)
- : TransportProtocol(icn_socket, nullptr),
- DatagramReassembly(icn_socket, this),
- inflightInterests_(1 << default_values::log_2_default_buffer_size),
- modMask_((1 << default_values::log_2_default_buffer_size) - 1) {
- icn_socket->getSocketOption(PORTAL, portal_);
- rtx_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
- probe_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
- sentinel_timer_ =
- std::make_unique<asio::steady_timer>(portal_->getIoService());
- round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
- initParams();
-}
-
-RTCTransportProtocol::~RTCTransportProtocol() {}
-
-void RTCTransportProtocol::resume() {
- if (is_running_) return;
-
- is_running_ = true;
- inflightInterestsCount_ = 0;
-
- probeRtt();
- sentinelTimer();
- newRound();
- scheduleNextInterests();
-
- portal_->runEventsLoop();
- is_running_ = false;
-}
-
-// private
-void RTCTransportProtocol::initParams() {
- portal_->setConsumerCallback(this);
- // controller var
- currentState_ = HICN_RTC_SYNC_STATE;
-
- // cwin var
- currentCWin_ = HICN_INITIAL_CWIN;
- maxCWin_ = HICN_INITIAL_CWIN_MAX;
-
- // names/packets var
- actualSegment_ = 0;
- inflightInterestsCount_ = 0;
- interestRetransmissions_.clear();
- lastSegNacked_ = 0;
- lastReceived_ = 0;
- lastReceivedTime_ = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- lastEvent_ = lastReceivedTime_;
- highestReceived_ = 0;
- firstSequenceInRound_ = 0;
-
- rtx_timer_used_ = false;
- for (int i = 0; i < (1 << default_values::log_2_default_buffer_size); i++) {
- inflightInterests_[i] = {0};
- }
-
- // stats
- firstPckReceived_ = false;
- receivedBytes_ = 0;
- sentInterest_ = 0;
- receivedData_ = 0;
- packetLost_ = 0;
- lossRecovered_ = 0;
- avgPacketSize_ = HICN_INIT_PACKET_SIZE;
- gotNack_ = false;
- gotFutureNack_ = 0;
- rounds_ = 0;
- roundsWithoutNacks_ = 0;
- pathTable_.clear();
-
- // CC var
- estimatedBw_ = 0.0;
- lossRate_ = 0.0;
- queuingDelay_ = 0.0;
- protocolState_ = HICN_RTC_NORMAL_STATE;
-
- producerPathLabels_[0] = 0;
- producerPathLabels_[1] = 0;
- initied = false;
-
- socket_->setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
- (uint32_t)HICN_RTC_INTEREST_LIFETIME);
-}
-
-// private
-void RTCTransportProtocol::reset() {
- initParams();
- probeRtt();
- sentinelTimer();
- newRound();
-}
-
-uint32_t max(uint32_t a, uint32_t b) {
- if (a > b)
- return a;
- else
- return b;
-}
-
-uint32_t min(uint32_t a, uint32_t b) {
- if (a < b)
- return a;
- else
- return b;
-}
-
-void RTCTransportProtocol::newRound() {
- round_timer_->expires_from_now(std::chrono::milliseconds(HICN_ROUND_LEN));
- round_timer_->async_wait([this](std::error_code ec) {
- if (ec) return;
- updateStats(HICN_ROUND_LEN);
- newRound();
- });
-}
-
-void RTCTransportProtocol::updateDelayStats(
- const ContentObject &content_object) {
- uint32_t segmentNumber = content_object.getName().getSuffix();
- uint32_t pkt = segmentNumber & modMask_;
-
- if (inflightInterests_[pkt].state != sent_) return;
-
- if (interestRetransmissions_.find(segmentNumber) !=
- interestRetransmissions_.end())
- // this packet was rtx at least once
- return;
-
- uint32_t pathLabel = content_object.getPathLabel();
-
- if (pathTable_.find(pathLabel) == pathTable_.end()) {
- // found a new path
- std::shared_ptr<RTCDataPath> newPath = std::make_shared<RTCDataPath>();
- pathTable_[pathLabel] = newPath;
- }
-
- // RTT measurements are useful both from NACKs and data packets
- uint64_t RTT = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count() -
- inflightInterests_[pkt].transmissionTime;
-
- pathTable_[pathLabel]->insertRttSample(RTT);
- auto payload = content_object.getPayload();
-
- // we collect OWD only for datapackets
- if (payload->length() != HICN_NACK_HEADER_SIZE) {
- uint64_t *senderTimeStamp = (uint64_t *)payload->data();
- int64_t OWD = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count() -
- *senderTimeStamp;
-
- pathTable_[pathLabel]->insertOwdSample(OWD);
- pathTable_[pathLabel]->computeInterArrivalGap(segmentNumber);
- } else {
- pathTable_[pathLabel]->receivedNack();
- }
-}
-
-void RTCTransportProtocol::updateStats(uint32_t round_duration) {
- if (pathTable_.empty()) return;
-
- if (receivedBytes_ != 0) {
- double bytesPerSec =
- (double)(receivedBytes_ *
- ((double)HICN_MILLI_IN_A_SEC / (double)round_duration));
- estimatedBw_ = (estimatedBw_ * HICN_ESTIMATED_BW_ALPHA) +
- ((1 - HICN_ESTIMATED_BW_ALPHA) * bytesPerSec);
- }
-
- uint64_t minRtt = UINT_MAX;
- uint64_t maxRtt = 0;
-
- for (auto it = pathTable_.begin(); it != pathTable_.end(); it++) {
- it->second->roundEnd();
- if (it->second->isActive()) {
- if (it->second->getMinRtt() < minRtt) {
- minRtt = it->second->getMinRtt();
- producerPathLabels_[0] = it->first;
- }
- if (it->second->getMinRtt() > maxRtt) {
- maxRtt = it->second->getMinRtt();
- producerPathLabels_[1] = it->first;
- }
- }
- }
-
- if (pathTable_.find(producerPathLabels_[0]) == pathTable_.end() ||
- pathTable_.find(producerPathLabels_[1]) == pathTable_.end())
- return; // this should not happen
-
- // as a queuing delay we keep the lowest one among the two paths
- // if one path is congested the forwarder should decide to do not
- // use it so it does not make sense to inform the application
- // that maybe we have a problem
- if (pathTable_[producerPathLabels_[0]]->getQueuingDealy() <
- pathTable_[producerPathLabels_[1]]->getQueuingDealy())
- queuingDelay_ = pathTable_[producerPathLabels_[0]]->getQueuingDealy();
- else
- queuingDelay_ = pathTable_[producerPathLabels_[1]]->getQueuingDealy();
-
- if (sentInterest_ != 0 && currentState_ == HICN_RTC_NORMAL_STATE) {
- uint32_t numberTheoricallyReceivedPackets_ =
- highestReceived_ - firstSequenceInRound_;
- double lossRate = 0;
- if (numberTheoricallyReceivedPackets_ != 0)
- lossRate = (double)((double)(packetLost_ - lossRecovered_) /
- (double)numberTheoricallyReceivedPackets_);
-
- if (lossRate < 0) lossRate = 0;
-
- if (initied) {
- lossRate_ = lossRate_ * HICN_ESTIMATED_LOSSES_ALPHA +
- (lossRate * (1 - HICN_ESTIMATED_LOSSES_ALPHA));
- } else {
- lossRate_ = lossRate;
- initied = true;
- }
- }
-
- if (avgPacketSize_ == 0) avgPacketSize_ = HICN_INIT_PACKET_SIZE;
-
- // for the BDP we use the max rtt, so that we calibrate the window on the
- // RTT of the slowest path. In this way we are sure that the window will
- // never be too small
- uint32_t BDP = (uint32_t)ceil(
- (estimatedBw_ *
- (double)((double)pathTable_[producerPathLabels_[1]]->getMinRtt() /
- (double)HICN_MILLI_IN_A_SEC) *
- HICN_BANDWIDTH_SLACK_FACTOR) /
- avgPacketSize_);
- uint32_t BW = (uint32_t)ceil(estimatedBw_);
- computeMaxWindow(BW, BDP);
-
- if (*stats_summary_) {
- // Send the stats to the app
- stats_->updateQueuingDelay(queuingDelay_);
- stats_->updateLossRatio(lossRate_);
- stats_->updateAverageRtt(pathTable_[producerPathLabels_[1]]->getMinRtt());
- (*stats_summary_)(*socket_->getInterface(), *stats_);
- }
- // bound also by interest lifitime* production rate
- if (!gotNack_) {
- roundsWithoutNacks_++;
- if (currentState_ == HICN_RTC_SYNC_STATE &&
- roundsWithoutNacks_ >= HICN_ROUNDS_IN_SYNC_BEFORE_SWITCH) {
- currentState_ = HICN_RTC_NORMAL_STATE;
- }
- } else {
- roundsWithoutNacks_ = 0;
- }
-
- updateCCState();
- updateWindow();
-
- if (queuingDelay_ > 25.0) {
- // this indicates that the client will go soon out of synch,
- // switch to synch mode
- if (currentState_ == HICN_RTC_NORMAL_STATE) {
- currentState_ = HICN_RTC_SYNC_STATE;
- }
- computeMaxWindow(BW, 0);
- increaseWindow();
- }
-
- // in any case we reset all the counters
-
- gotNack_ = false;
- gotFutureNack_ = 0;
- receivedBytes_ = 0;
- sentInterest_ = 0;
- receivedData_ = 0;
- packetLost_ = 0;
- lossRecovered_ = 0;
- rounds_++;
- firstSequenceInRound_ = highestReceived_;
-}
-
-void RTCTransportProtocol::updateCCState() {
- // TODO
-}
-
-void RTCTransportProtocol::computeMaxWindow(uint32_t productionRate,
- uint32_t BDPWin) {
- if (productionRate ==
- 0) // we have no info about the producer, keep the previous maxCWin
- return;
-
- uint32_t interestLifetime = default_values::interest_lifetime;
- socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
- interestLifetime);
- uint32_t maxWaintingInterest = (uint32_t)ceil(
- (productionRate / avgPacketSize_) *
- (double)((double)(interestLifetime *
- HICN_INTEREST_LIFETIME_REDUCTION_FACTOR) /
- (double)HICN_MILLI_IN_A_SEC));
-
- if (currentState_ == HICN_RTC_SYNC_STATE) {
- // in this case we do not limit the window with the BDP, beacuse most
- // likely it is wrong
- maxCWin_ = maxWaintingInterest;
- return;
- }
-
- // currentState = RTC_NORMAL_STATE
- if (BDPWin != 0) {
- maxCWin_ = (uint32_t)ceil((double)BDPWin +
- (((double)BDPWin * 30.0) / 100.0)); // BDP + 30%
- } else {
- maxCWin_ = min(maxWaintingInterest, maxCWin_);
- }
-
- if (maxCWin_ < HICN_MIN_CWIN) maxCWin_ = HICN_MIN_CWIN;
-}
-
-void RTCTransportProtocol::updateWindow() {
- if (currentState_ == HICN_RTC_SYNC_STATE) return;
-
- if (estimatedBw_ == 0) return;
-
- if (currentCWin_ < maxCWin_ * 0.9) {
- currentCWin_ =
- min(maxCWin_, (uint32_t)(currentCWin_ * HICN_WIN_INCREASE_FACTOR));
- } else if (currentCWin_ > maxCWin_) {
- currentCWin_ =
- max((uint32_t)(currentCWin_ * HICN_WIN_DECREASE_FACTOR), HICN_MIN_CWIN);
- }
-}
-
-void RTCTransportProtocol::decreaseWindow() {
- // this is used only in SYNC mode
- if (currentState_ == HICN_RTC_NORMAL_STATE) return;
-
- if (gotFutureNack_ == 1)
- currentCWin_ = min((currentCWin_ - 1),
- (uint32_t)ceil((double)maxCWin_ * 0.66)); // 2/3
- else
- currentCWin_--;
-
- currentCWin_ = max(currentCWin_, HICN_MIN_CWIN);
-}
-
-void RTCTransportProtocol::increaseWindow() {
- // this is used only in SYNC mode
- if (currentState_ == HICN_RTC_NORMAL_STATE) return;
-
- // we need to be carefull to do not increase the window to much
- if (currentCWin_ < ((double)maxCWin_ * 0.7)) {
- currentCWin_ = currentCWin_ + 1; // exponential
- } else {
- currentCWin_ = min(
- maxCWin_,
- (uint32_t)ceil(currentCWin_ + (1.0 / (double)currentCWin_))); // linear
- }
-}
-
-void RTCTransportProtocol::probeRtt() {
- probe_timer_->expires_from_now(std::chrono::milliseconds(1000));
- probe_timer_->async_wait([this](std::error_code ec) {
- if (ec) return;
- probeRtt();
- });
-
- // To avoid sending the first probe, because the transport is not running yet
- if (is_first_ && !is_running_) return;
-
- time_sent_probe_ = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- Name *interest_name = nullptr;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
- &interest_name);
- // get a random numbe in the probe seq range
- std::default_random_engine eng((std::random_device())());
- std::uniform_int_distribution<uint32_t> idis(HICN_MIN_PROBE_SEQ,
- HICN_MAX_PROBE_SEQ);
- probe_seq_number_ = idis(eng);
- interest_name->setSuffix(probe_seq_number_);
-
- // we considere the probe as a rtx so that we do not incresea inFlightInt
- received_probe_ = false;
- TRANSPORT_LOGD("Send content interest %u (probeRtt)",
- interest_name->getSuffix());
- sendInterest(interest_name, true);
-}
-
-void RTCTransportProtocol::sendInterest(Name *interest_name, bool rtx) {
- auto interest = getPacket();
- interest->setName(*interest_name);
-
- uint32_t interestLifetime = default_values::interest_lifetime;
- socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
- interestLifetime);
- interest->setLifetime(uint32_t(interestLifetime));
-
- if (*on_interest_output_) {
- (*on_interest_output_)(*socket_->getInterface(), *interest);
- }
-
- if (TRANSPORT_EXPECT_FALSE(!is_running_ && !is_first_)) {
- return;
- }
-
- portal_->sendInterest(std::move(interest));
-
- sentInterest_++;
-
- if (!rtx) {
- packets_in_window_[interest_name->getSuffix()] = 0;
- inflightInterestsCount_++;
- }
-}
-
-void RTCTransportProtocol::scheduleNextInterests() {
- if (!is_running_ && !is_first_) return;
-
- TRANSPORT_LOGD("----- [window %u - inflight_interests %u = %d] -----",
- currentCWin_, inflightInterestsCount_,
- currentCWin_ - inflightInterestsCount_);
-
- while (inflightInterestsCount_ < currentCWin_) {
- Name *interest_name = nullptr;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
- &interest_name);
-
- interest_name->setSuffix(actualSegment_);
-
- // if the producer socket is not stated (does not reply even with nacks)
- // we keep asking for something without marking anything as lost (see
- // timeout). In this way when the producer socket will start the
- // consumer socket will not miss any packet
- if (TRANSPORT_EXPECT_FALSE(!firstPckReceived_)) {
- uint32_t pkt = actualSegment_ & modMask_;
- inflightInterests_[pkt].state = sent_;
- inflightInterests_[pkt].sequence = actualSegment_;
- actualSegment_ = (actualSegment_ + 1) % HICN_MIN_PROBE_SEQ;
- TRANSPORT_LOGD(
- "Send content interest %u (scheduleNextInterests no replies)",
- interest_name->getSuffix());
- sendInterest(interest_name, false);
- return;
- }
-
- // we send the packet only if it is not pending yet
- // notice that this is not true for rtx packets
- if (portal_->interestIsPending(*interest_name)) {
- actualSegment_ = (actualSegment_ + 1) % HICN_MIN_PROBE_SEQ;
- continue;
- }
-
- uint32_t pkt = actualSegment_ & modMask_;
- // if we already reacevied the content we don't ask it again
- if (inflightInterests_[pkt].state == received_ &&
- inflightInterests_[pkt].sequence == actualSegment_) {
- actualSegment_ = (actualSegment_ + 1) % HICN_MIN_PROBE_SEQ;
- continue;
- }
-
- // same if the packet is lost
- if (inflightInterests_[pkt].state == lost_ &&
- inflightInterests_[pkt].sequence == actualSegment_) {
- actualSegment_ = (actualSegment_ + 1) % HICN_MIN_PROBE_SEQ;
- continue;
- }
-
- inflightInterests_[pkt].transmissionTime =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- // here the packet can be in any state except for lost or recevied
- inflightInterests_[pkt].state = sent_;
- inflightInterests_[pkt].sequence = actualSegment_;
- actualSegment_ = (actualSegment_ + 1) % HICN_MIN_PROBE_SEQ;
-
- TRANSPORT_LOGD("Send content interest %u (scheduleNextInterests)",
- interest_name->getSuffix());
- sendInterest(interest_name, false);
- }
-
- TRANSPORT_LOGD("----- end of scheduleNextInterest -----");
-}
-
-bool RTCTransportProtocol::verifyKeyPackets() {
- // Not yet implemented
- return false;
-}
-
-void RTCTransportProtocol::sentinelTimer() {
- uint32_t wait = 50;
-
- if (pathTable_.find(producerPathLabels_[0]) != pathTable_.end() &&
- pathTable_.find(producerPathLabels_[1]) != pathTable_.end()) {
- // we have all the info to set the timers
- wait = round(pathTable_[producerPathLabels_[0]]->getInterArrivalGap());
- if (wait == 0) wait = 1;
- }
-
- sentinel_timer_->expires_from_now(std::chrono::milliseconds(wait));
- sentinel_timer_->async_wait([this](std::error_code ec) {
- if (ec) return;
-
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- if (pathTable_.find(producerPathLabels_[0]) == pathTable_.end() ||
- pathTable_.find(producerPathLabels_[1]) == pathTable_.end()) {
- // we have no info, so we send again
-
- for (auto it = packets_in_window_.begin(); it != packets_in_window_.end();
- it++) {
- uint32_t pkt = it->first & modMask_;
- if (inflightInterests_[pkt].sequence == it->first) {
- inflightInterests_[pkt].transmissionTime = now;
- Name *interest_name = nullptr;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
- &interest_name);
- interest_name->setSuffix(it->first);
- it->second++;
- sendInterest(interest_name, true);
- }
- }
- } else {
- uint64_t max_waiting_time = // wait at least 50ms
- (pathTable_[producerPathLabels_[1]]->getMinRtt() -
- pathTable_[producerPathLabels_[0]]->getMinRtt()) +
- (ceil(pathTable_[producerPathLabels_[0]]->getInterArrivalGap()) * 50);
-
- if ((currentState_ == HICN_RTC_NORMAL_STATE) &&
- (inflightInterestsCount_ >= currentCWin_) &&
- ((now - lastEvent_) > max_waiting_time) && (lossRate_ >= 0.05)) {
- uint64_t RTT = pathTable_[producerPathLabels_[1]]->getMinRtt();
-
- for (auto it = packets_in_window_.begin();
- it != packets_in_window_.end(); it++) {
- uint32_t pkt = it->first & modMask_;
- if (inflightInterests_[pkt].sequence == it->first &&
- ((now - inflightInterests_[pkt].transmissionTime) >= RTT)) {
- inflightInterests_[pkt].transmissionTime = now;
- Name *interest_name = nullptr;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
- &interest_name);
- interest_name->setSuffix(it->first);
- it->second++;
- sendInterest(interest_name, true);
- }
- }
- }
- }
-
- sentinelTimer();
- });
-}
-void RTCTransportProtocol::addRetransmissions(uint32_t val) {
- // add only val in the rtx list
- addRetransmissions(val, val + 1);
-}
-
-void RTCTransportProtocol::addRetransmissions(uint32_t start, uint32_t stop) {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- bool new_rtx = false;
- for (uint32_t i = start; i < stop; i++) {
- auto it = interestRetransmissions_.find(i);
- if (it == interestRetransmissions_.end()) {
- uint32_t pkt = i & modMask_;
- if (lastSegNacked_ <= i && inflightInterests_[pkt].state != received_) {
- // it must be larger than the last past nack received
- packetLost_++;
- interestRetransmissions_[i] = 0;
- uint32_t pkt = i & modMask_;
- // we reset the transmission time setting to now, so that rtx will
- // happne in one RTT on waint one inter arrival gap
- inflightInterests_[pkt].transmissionTime = now;
- new_rtx = true;
- }
- } // if the retransmission is already there the rtx timer will
- // take care of it
- }
-
- // in case a new rtx is added to the map we need to run checkRtx()
- if (new_rtx) {
- if (rtx_timer_used_) {
- // if a timer is pending we need to delete it
- rtx_timer_->cancel();
- rtx_timer_used_ = false;
- }
- checkRtx();
- }
-}
-
-uint64_t RTCTransportProtocol::retransmit() {
- auto it = interestRetransmissions_.begin();
-
- // cut len to max HICN_MAX_RTX_SIZE
- // since we use a map, the smaller (and so the older) sequence number are at
- // the beginnin of the map
- while (interestRetransmissions_.size() > HICN_MAX_RTX_SIZE) {
- it = interestRetransmissions_.erase(it);
- }
-
- it = interestRetransmissions_.begin();
- uint64_t smallest_timeout = ULONG_MAX;
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- while (it != interestRetransmissions_.end()) {
- uint32_t pkt = it->first & modMask_;
-
- if (inflightInterests_[pkt].sequence != it->first) {
- // this packet is not anymore in the inflight buffer, erase it
- it = interestRetransmissions_.erase(it);
- continue;
- }
-
- // we retransmitted the packet too many times
- if (it->second >= HICN_MAX_RTX) {
- it = interestRetransmissions_.erase(it);
- continue;
- }
-
- // this packet is too old
- if ((lastReceived_ > it->first) &&
- (lastReceived_ - it->first) > HICN_MAX_RTX_MAX_AGE) {
- it = interestRetransmissions_.erase(it);
- continue;
- }
-
- uint64_t rtx_time = now;
-
- if (it->second == 0) {
- // first rtx
- if (producerPathLabels_[0] != producerPathLabels_[1]) {
- // multipath
- if (pathTable_.find(producerPathLabels_[0]) != pathTable_.end() &&
- pathTable_.find(producerPathLabels_[1]) != pathTable_.end() &&
- (pathTable_[producerPathLabels_[0]]->getInterArrivalGap() <
- HICN_MIN_INTER_ARRIVAL_GAP)) {
- rtx_time = lastReceivedTime_ +
- (pathTable_[producerPathLabels_[1]]->getMinRtt() -
- pathTable_[producerPathLabels_[0]]->getMinRtt()) +
- pathTable_[producerPathLabels_[0]]->getInterArrivalGap();
- } // else low rate producer, send it immediatly
- } else {
- // single path
- if (pathTable_.find(producerPathLabels_[0]) != pathTable_.end() &&
- (pathTable_[producerPathLabels_[0]]->getInterArrivalGap() <
- HICN_MIN_INTER_ARRIVAL_GAP)) {
- rtx_time = lastReceivedTime_ +
- pathTable_[producerPathLabels_[0]]->getInterArrivalGap();
- } // else low rate producer send immediatly
- }
- } else {
- // second or plus rtx, wait for the min rtt
- if (pathTable_.find(producerPathLabels_[0]) != pathTable_.end()) {
- uint64_t sent_time = inflightInterests_[pkt].transmissionTime;
- rtx_time = sent_time + pathTable_[producerPathLabels_[0]]->getMinRtt();
- } // if we don't have info we send it immediatly
- }
-
- if (now >= rtx_time) {
- inflightInterests_[pkt].transmissionTime = now;
- it->second++;
-
- Name *interest_name = nullptr;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
- &interest_name);
- interest_name->setSuffix(it->first);
- TRANSPORT_LOGD("Send content interest %u (retransmit)",
- interest_name->getSuffix());
- sendInterest(interest_name, true);
- } else if (rtx_time < smallest_timeout) {
- smallest_timeout = rtx_time;
- }
-
- ++it;
- }
- return smallest_timeout;
-}
-
-void RTCTransportProtocol::checkRtx() {
- if (interestRetransmissions_.empty()) {
- rtx_timer_used_ = false;
- return;
- }
-
- uint64_t next_timeout = retransmit();
- uint64_t wait = 1;
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- if (next_timeout != ULONG_MAX && now < next_timeout) {
- wait = next_timeout - now;
- }
- rtx_timer_used_ = true;
- rtx_timer_->expires_from_now(std::chrono::milliseconds(wait));
- rtx_timer_->async_wait([this](std::error_code ec) {
- if (ec) return;
- rtx_timer_used_ = false;
- checkRtx();
- });
-}
-
-void RTCTransportProtocol::onTimeout(Interest::Ptr &&interest) {
- uint32_t segmentNumber = interest->getName().getSuffix();
-
- if (segmentNumber >= HICN_MIN_PROBE_SEQ) {
- // this is a timeout on a probe, do nothing
- return;
- }
-
- uint32_t pkt = segmentNumber & modMask_;
-
- if (TRANSPORT_EXPECT_FALSE(!firstPckReceived_)) {
- // we do nothing, and we keep asking the same stuff over
- // and over until we get at least a packet
- inflightInterestsCount_--;
- lastEvent_ = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- packets_in_window_.erase(segmentNumber);
- scheduleNextInterests();
- return;
- }
-
- if (inflightInterests_[pkt].state == sent_) {
- lastEvent_ = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- packets_in_window_.erase(segmentNumber);
- inflightInterestsCount_--;
- }
-
- // check how many times we sent this packet
- auto it = interestRetransmissions_.find(segmentNumber);
- if (it != interestRetransmissions_.end() && it->second >= HICN_MAX_RTX) {
- inflightInterests_[pkt].state = lost_;
- }
-
- if (inflightInterests_[pkt].state == sent_) {
- inflightInterests_[pkt].state = timeout1_;
- } else if (inflightInterests_[pkt].state == timeout1_) {
- inflightInterests_[pkt].state = timeout2_;
- } else if (inflightInterests_[pkt].state == timeout2_) {
- inflightInterests_[pkt].state = lost_;
- }
-
- if (inflightInterests_[pkt].state == lost_) {
- interestRetransmissions_.erase(segmentNumber);
- } else {
- addRetransmissions(segmentNumber);
- }
-
- scheduleNextInterests();
-}
-
-bool RTCTransportProtocol::onNack(const ContentObject &content_object,
- bool rtx) {
- uint32_t *payload = (uint32_t *)content_object.getPayload()->data();
- uint32_t productionSeg = *payload;
- uint32_t productionRate = *(++payload);
- uint32_t nackSegment = content_object.getName().getSuffix();
-
- bool old_nack = false;
-
- // if we did not received anything between lastReceived_ + 1 and productionSeg
- // most likelly some packets got lost
- if (lastReceived_ != 0) {
- addRetransmissions(lastReceived_ + 1, productionSeg);
- }
-
- if (!rtx) {
- gotNack_ = true;
- // we synch the estimated production rate with the actual one
- estimatedBw_ = (double)productionRate;
- }
-
- if (productionSeg > nackSegment) {
- // we are asking for stuff produced in the past
- actualSegment_ = max(productionSeg, actualSegment_) % HICN_MIN_PROBE_SEQ;
-
- if (!rtx) {
- if (currentState_ == HICN_RTC_NORMAL_STATE) {
- currentState_ = HICN_RTC_SYNC_STATE;
- }
-
- computeMaxWindow(productionRate, 0);
- increaseWindow();
- }
-
- lastSegNacked_ = productionSeg;
- old_nack = true;
-
- } else if (productionSeg < nackSegment) {
- actualSegment_ = productionSeg % HICN_MIN_PROBE_SEQ;
-
- if (!rtx) {
- // we are asking stuff in the future
- gotFutureNack_++;
- computeMaxWindow(productionRate, 0);
- decreaseWindow();
-
- if (currentState_ == HICN_RTC_SYNC_STATE) {
- currentState_ = HICN_RTC_NORMAL_STATE;
- }
- }
- } else {
- // we are asking the right thing, but the producer is slow
- // keep doing the same until the packet is produced
- actualSegment_ = productionSeg % HICN_MIN_PROBE_SEQ;
- }
-
- return old_nack;
-}
-
-void RTCTransportProtocol::onContentObject(
- Interest::Ptr &&interest, ContentObject::Ptr &&content_object) {
- // as soon as we get a packet firstPckReceived_ will never be false
- firstPckReceived_ = true;
-
- auto payload = content_object->getPayload();
- uint32_t payload_size = (uint32_t)payload->length();
- uint32_t segmentNumber = content_object->getName().getSuffix();
- uint32_t pkt = segmentNumber & modMask_;
-
- if (*on_content_object_input_) {
- (*on_content_object_input_)(*socket_->getInterface(), *content_object);
- }
-
- if (segmentNumber >= HICN_MIN_PROBE_SEQ) {
- TRANSPORT_LOGD("Received probe %u", segmentNumber);
- if (segmentNumber == probe_seq_number_ && !received_probe_) {
- received_probe_ = true;
-
- uint32_t pathLabel = content_object->getPathLabel();
- if (pathTable_.find(pathLabel) == pathTable_.end()) {
- std::shared_ptr<RTCDataPath> newPath = std::make_shared<RTCDataPath>();
- pathTable_[pathLabel] = newPath;
- }
-
- // this is the expected probe, update the RTT and drop the packet
- uint64_t RTT = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count() -
- time_sent_probe_;
-
- pathTable_[pathLabel]->insertRttSample(RTT);
- pathTable_[pathLabel]->receivedNack();
- }
- return;
- }
-
- // check if the packet is a rtx
- bool is_rtx = false;
- if (interestRetransmissions_.find(segmentNumber) !=
- interestRetransmissions_.end()) {
- is_rtx = true;
- } else {
- auto it_win = packets_in_window_.find(segmentNumber);
- if (it_win != packets_in_window_.end() && it_win->second != 0)
- is_rtx = true;
- }
-
- if (payload_size == HICN_NACK_HEADER_SIZE) {
- TRANSPORT_LOGD("Received nack %u", segmentNumber);
-
- if (inflightInterests_[pkt].state == sent_) {
- lastEvent_ = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- packets_in_window_.erase(segmentNumber);
- inflightInterestsCount_--;
- }
-
- bool old_nack = false;
-
- if (!is_rtx) {
- // this is not a retransmitted packet
- old_nack = onNack(*content_object, false);
- updateDelayStats(*content_object);
- } else {
- old_nack = onNack(*content_object, true);
- }
-
- // the nacked_ state is used only to avoid to decrease
- // inflightInterestsCount_ multiple times. In fact, every time that we
- // receive an event related to an interest (timeout, nacked, content) we
- // cange the state. In this way we are sure that we do not decrease twice
- // the counter
- if (old_nack) {
- inflightInterests_[pkt].state = lost_;
- interestRetransmissions_.erase(segmentNumber);
- } else {
- inflightInterests_[pkt].state = nacked_;
- }
-
- } else {
- TRANSPORT_LOGD("Received content %u", segmentNumber);
-
- avgPacketSize_ = (HICN_ESTIMATED_PACKET_SIZE * avgPacketSize_) +
- ((1 - HICN_ESTIMATED_PACKET_SIZE) * payload->length());
-
- receivedBytes_ += (uint32_t)(content_object->headerSize() +
- content_object->payloadSize());
-
- if (inflightInterests_[pkt].state == sent_) {
- lastEvent_ = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- packets_in_window_.erase(segmentNumber);
- inflightInterestsCount_--; // packet sent without timeouts
- }
-
- if (inflightInterests_[pkt].state == sent_ && !is_rtx) {
- // delay stats are computed only for non retransmitted data
- updateDelayStats(*content_object);
- }
-
- addRetransmissions(lastReceived_ + 1, segmentNumber);
- if (segmentNumber > highestReceived_) {
- highestReceived_ = segmentNumber;
- }
- if (segmentNumber > lastReceived_) {
- lastReceived_ = segmentNumber;
- lastReceivedTime_ =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- }
- receivedData_++;
- inflightInterests_[pkt].state = received_;
-
- auto it = interestRetransmissions_.find(segmentNumber);
- if (it != interestRetransmissions_.end()) lossRecovered_++;
-
- interestRetransmissions_.erase(segmentNumber);
-
- reassemble(std::move(content_object));
- increaseWindow();
- }
-
- scheduleNextInterests();
-}
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/rtc.h b/libtransport/src/protocols/rtc.h
deleted file mode 100644
index 9f1bcc25b..000000000
--- a/libtransport/src/protocols/rtc.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiTC_SYNC_STATE
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <protocols/datagram_reassembly.h>
-#include <protocols/protocol.h>
-#include <protocols/rtc_data_path.h>
-
-#include <map>
-#include <queue>
-#include <unordered_map>
-
-// algorithm state
-#define HICN_RTC_SYNC_STATE 0
-#define HICN_RTC_NORMAL_STATE 1
-#define HICN_ROUNDS_IN_SYNC_BEFORE_SWITCH 3
-
-// packet constants
-#define HICN_INIT_PACKET_SIZE 1300 // bytes
-#define HICN_PACKET_HEADER_SIZE 60 // bytes ipv6+tcp
-#define HICN_NACK_HEADER_SIZE 8 // bytes
-#define HICN_TIMESTAMP_SIZE 8 // bytes
-#define HICN_RTC_INTEREST_LIFETIME 1000 // ms
-
-// rtt measurement
-// normal interests for data goes from 0 to
-// HICN_MIN_PROBE_SEQ, the rest is reserverd for
-// probes
-#define HICN_MIN_PROBE_SEQ 0xefffffff
-#define HICN_MAX_PROBE_SEQ 0xffffffff
-
-// controller constant
-#define HICN_ROUND_LEN \
- 200 // ms interval of time on which
- // we take decisions / measurements
-#define HICN_MAX_RTX 10
-#define HICN_MAX_RTX_SIZE 1024
-#define HICN_MAX_RTX_MAX_AGE 10000
-#define HICN_MIN_RTT_WIN 30 // rounds
-#define HICN_MIN_INTER_ARRIVAL_GAP 100 // ms
-
-// cwin
-#define HICN_INITIAL_CWIN 1 // packets
-#define HICN_INITIAL_CWIN_MAX 100000 // packets
-#define HICN_MIN_CWIN 10 // packets
-#define HICN_WIN_INCREASE_FACTOR 1.5
-#define HICN_WIN_DECREASE_FACTOR 0.9
-
-// statistics constants
-#define HICN_BANDWIDTH_SLACK_FACTOR 1.8
-#define HICN_ESTIMATED_BW_ALPHA 0.7
-#define HICN_ESTIMATED_PACKET_SIZE 0.7
-#define HICN_ESTIMATED_LOSSES_ALPHA 0.8
-#define HICN_INTEREST_LIFETIME_REDUCTION_FACTOR 0.8
-
-// other constants
-#define HICN_NANO_IN_A_SEC 1000000000
-#define HICN_MICRO_IN_A_SEC 1000000
-#define HICN_MILLI_IN_A_SEC 1000
-
-namespace transport {
-
-namespace protocol {
-
-enum packetState { sent_, nacked_, received_, timeout1_, timeout2_, lost_ };
-
-typedef enum packetState packetState_t;
-
-struct sentInterest {
- uint64_t transmissionTime;
- uint32_t sequence; // sequence number of the interest sent
- // to handle seq % buffer_size
- packetState_t state; // see packet state
-};
-
-class RTCTransportProtocol : public TransportProtocol,
- public DatagramReassembly {
- public:
- RTCTransportProtocol(implementation::ConsumerSocket *icnet_socket);
-
- ~RTCTransportProtocol();
-
- using TransportProtocol::start;
-
- using TransportProtocol::stop;
-
- void resume() override;
-
- bool verifyKeyPackets() override;
-
- private:
- // algo functions
- void initParams();
- void reset() override;
-
- // CC functions
- void updateDelayStats(const ContentObject &content_object);
- void updateStats(uint32_t round_duration);
- void updateCCState();
- void computeMaxWindow(uint32_t productionRate, uint32_t BDPWin);
- void updateWindow();
- void decreaseWindow();
- void increaseWindow();
- void resetPreviousWindow();
-
- // packet functions
- void sendInterest(Name *interest_name, bool rtx);
- void scheduleNextInterests() override;
- void sentinelTimer();
- void addRetransmissions(uint32_t val);
- void addRetransmissions(uint32_t start, uint32_t stop);
- uint64_t retransmit();
- void checkRtx();
- void probeRtt();
- void newRound();
- void onTimeout(Interest::Ptr &&interest) override;
- bool onNack(const ContentObject &content_object, bool rtx);
- void onContentObject(Interest::Ptr &&interest,
- ContentObject::Ptr &&content_object) override;
- void onPacketDropped(Interest::Ptr &&interest,
- ContentObject::Ptr &&content_object) override {}
- void onReassemblyFailed(std::uint32_t missing_segment) override {}
-
- TRANSPORT_ALWAYS_INLINE virtual void reassemble(
- ContentObject::Ptr &&content_object) override {
- auto read_buffer = content_object->getPayload();
- read_buffer->trimStart(HICN_TIMESTAMP_SIZE);
- Reassembly::read_buffer_ = std::move(read_buffer);
- Reassembly::notifyApplication();
- }
-
- // controller var
- std::unique_ptr<asio::steady_timer> round_timer_;
- unsigned currentState_;
-
- // cwin var
- uint32_t currentCWin_;
- uint32_t maxCWin_;
-
- // names/packets var
- uint32_t actualSegment_;
- uint32_t inflightInterestsCount_;
- // map seq to rtx
- std::map<uint32_t, uint8_t> interestRetransmissions_;
- bool rtx_timer_used_;
- std::unique_ptr<asio::steady_timer> rtx_timer_;
- std::vector<sentInterest> inflightInterests_;
- uint32_t lastSegNacked_; // indicates the segment id in the last received
- // past Nack. we do not ask for retransmissions
- // for samething that is older than this value.
- uint32_t lastReceived_; // segment of the last content object received
- // indicates the base of the window on the client
- uint64_t lastReceivedTime_; // time at which we recevied the
- // lastReceived_ packet
-
- // sentinel
- // if all packets in the window get lost we need something that
- // wakes up our consumer socket. Interest timeouts set to 1 sec
- // expire too late. This timers expire much sooner and if it
- // detects that all the interest in the window may be lost
- // it sends all of them again
- std::unique_ptr<asio::steady_timer> sentinel_timer_;
- uint64_t lastEvent_; // time at which we removed a pending
- // interest from the window
- std::unordered_map<uint32_t, uint8_t> packets_in_window_;
-
- // rtt probes
- // the RTC transport tends to overestimate the RTT
- // du to the production time on the server side
- // once per second we send an interest for wich we know
- // we will get a nack. This nack will keep our estimation
- // close to the reality
- std::unique_ptr<asio::steady_timer> probe_timer_;
- uint64_t time_sent_probe_;
- uint32_t probe_seq_number_;
- bool received_probe_;
-
- uint32_t modMask_;
-
- // stats
- bool firstPckReceived_;
- uint32_t receivedBytes_;
- uint32_t sentInterest_;
- uint32_t receivedData_;
- int32_t packetLost_;
- int32_t lossRecovered_;
- uint32_t firstSequenceInRound_;
- uint32_t highestReceived_;
- double avgPacketSize_;
- bool gotNack_;
- uint32_t gotFutureNack_;
- uint32_t rounds_;
- uint32_t roundsWithoutNacks_;
-
- // we keep track of up two paths (if only one path is in use
- // the two values in the vector will be the same)
- // position 0 stores the path with minRTT
- // position 1 stores the path with maxRTT
- uint32_t producerPathLabels_[2];
-
- std::unordered_map<uint32_t, std::shared_ptr<RTCDataPath>> pathTable_;
- uint32_t roundCounter_;
-
- // CC var
- double estimatedBw_;
- double lossRate_;
- double queuingDelay_;
- unsigned protocolState_;
-
- bool initied;
-};
-
-} // namespace protocol
-
-} // namespace transport
diff --git a/libtransport/src/protocols/rtc/CMakeLists.txt b/libtransport/src/protocols/rtc/CMakeLists.txt
index 77f065d0e..873b345d0 100644
--- a/libtransport/src/protocols/rtc/CMakeLists.txt
+++ b/libtransport/src/protocols/rtc/CMakeLists.txt
@@ -11,27 +11,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/probe_handler.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_ldr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_consts.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_indexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_ldr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_packet.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc.h
${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_queue.h
- ${CMAKE_CURRENT_SOURCE_DIR}/probe_handler.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_packet.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_reassembly.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.h
)
list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/probe_handler.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc_ldr.cc
${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_queue.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/probe_handler.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.cc
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/protocols/rtc/congestion_detection.cc b/libtransport/src/protocols/rtc/congestion_detection.cc
deleted file mode 100644
index e2d44ae66..000000000
--- a/libtransport/src/protocols/rtc/congestion_detection.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/utils/log.h>
-#include <protocols/rtc/congestion_detection.h>
-
-namespace transport {
-
-namespace protocol {
-
-namespace rtc {
-
-CongestionDetection::CongestionDetection()
- : cc_estimator_(), last_processed_chunk_() {}
-
-CongestionDetection::~CongestionDetection() {}
-
-void CongestionDetection::updateStats() {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- if (chunks_number_.empty()) return;
-
- uint32_t chunk_number = chunks_number_.front();
-
- while (chunks_[chunk_number].getReceivedTime() + HICN_CC_STATS_MAX_DELAY_MS <
- now ||
- chunks_[chunk_number].isComplete()) {
- if (chunk_number == last_processed_chunk_.getFrameSeqNum() + 1) {
- chunks_[chunk_number].setPreviousSentTime(
- last_processed_chunk_.getSentTime());
-
- chunks_[chunk_number].setPreviousReceivedTime(
- last_processed_chunk_.getReceivedTime());
- cc_estimator_.Update(chunks_[chunk_number].getReceivedDelta(),
- chunks_[chunk_number].getSentDelta(),
- chunks_[chunk_number].getSentTime(),
- chunks_[chunk_number].getReceivedTime(),
- chunks_[chunk_number].getFrameSize(), true);
-
- } else {
- TRANSPORT_LOGD(
- "CongestionDetection::updateStats frame %u but not the \
- previous one, last one was %u currentFrame %u",
- chunk_number, last_processed_chunk_.getFrameSeqNum(),
- chunks_[chunk_number].getFrameSeqNum());
- }
-
- last_processed_chunk_ = chunks_[chunk_number];
-
- chunks_.erase(chunk_number);
-
- chunks_number_.pop();
- if (chunks_number_.empty()) break;
-
- chunk_number = chunks_number_.front();
- }
-}
-
-void CongestionDetection::addPacket(const core::ContentObject &content_object) {
- auto payload = content_object.getPayload();
- uint32_t payload_size = (uint32_t)payload->length();
- uint32_t segmentNumber = content_object.getName().getSuffix();
- // uint32_t pkt = segmentNumber & modMask_;
- uint64_t *sentTimePtr = (uint64_t *)payload->data();
-
- // this is just for testing with hiperf, assuming a frame is 10 pkts
- // in the final version, the split should be based on the timestamp in the pkt
- uint32_t frameNum = (int)(segmentNumber / HICN_CC_STATS_CHUNK_SIZE);
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
-
- if (chunks_.find(frameNum) == chunks_.end()) {
- // new chunk of pkts or out of order
- if (last_processed_chunk_.getFrameSeqNum() > frameNum)
- return; // out of order and we already processed the chunk
-
- chunks_[frameNum] = FrameStats(frameNum, HICN_CC_STATS_CHUNK_SIZE);
- chunks_number_.push(frameNum);
- }
-
- chunks_[frameNum].addPacket(*sentTimePtr, now, payload_size);
-}
-
-} // namespace rtc
-} // namespace protocol
-} // namespace transport
diff --git a/libtransport/src/protocols/rtc/congestion_detection.h b/libtransport/src/protocols/rtc/congestion_detection.h
deleted file mode 100644
index 17f4aa54c..000000000
--- a/libtransport/src/protocols/rtc/congestion_detection.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/core/content_object.h>
-#include <protocols/rtc/trendline_estimator.h>
-
-#include <map>
-#include <queue>
-
-#define HICN_CC_STATS_CHUNK_SIZE 10
-#define HICN_CC_STATS_MAX_DELAY_MS 100
-
-namespace transport {
-
-namespace protocol {
-
-namespace rtc {
-
-class FrameStats {
- public:
- FrameStats()
- : frame_num_(0),
- sent_time_(0),
- received_time_(0),
- previous_sent_time_(0),
- previous_received_time_(0),
- size_(0),
- received_pkt_m(0),
- burst_size_m(HICN_CC_STATS_CHUNK_SIZE){};
-
- FrameStats(uint32_t burst_size)
- : frame_num_(0),
- sent_time_(0),
- received_time_(0),
- previous_sent_time_(0),
- previous_received_time_(0),
- size_(0),
- received_pkt_m(0),
- burst_size_m(burst_size){};
-
- FrameStats(uint32_t frame_num, uint32_t burst_size)
- : frame_num_(frame_num),
- sent_time_(0),
- received_time_(0),
- previous_sent_time_(0),
- previous_received_time_(0),
- size_(0),
- received_pkt_m(0),
- burst_size_m(burst_size){};
-
- FrameStats(uint32_t frame_num, uint64_t sent_time, uint64_t received_time,
- uint32_t size, FrameStats previousFrame, uint32_t burst_size)
- : frame_num_(frame_num),
- sent_time_(sent_time),
- received_time_(received_time),
- previous_sent_time_(previousFrame.getSentTime()),
- previous_received_time_(previousFrame.getReceivedTime()),
- size_(size),
- received_pkt_m(1),
- burst_size_m(burst_size){};
-
- void addPacket(uint64_t sent_time, uint64_t received_time, uint32_t size) {
- size_ += size;
- sent_time_ =
- (sent_time_ == 0) ? sent_time : std::min(sent_time_, sent_time);
- received_time_ = std::max(received_time, received_time_);
- received_pkt_m++;
- }
-
- bool isComplete() { return received_pkt_m == burst_size_m; }
-
- uint32_t getFrameSeqNum() const { return frame_num_; }
- uint64_t getSentTime() const { return sent_time_; }
- uint64_t getReceivedTime() const { return received_time_; }
- uint32_t getFrameSize() const { return size_; }
-
- void setPreviousReceivedTime(uint64_t time) {
- previous_received_time_ = time;
- }
- void setPreviousSentTime(uint64_t time) { previous_sent_time_ = time; }
-
- // todo manage first frame
- double getReceivedDelta() {
- return static_cast<double>(received_time_ - previous_received_time_);
- }
- double getSentDelta() {
- return static_cast<double>(sent_time_ - previous_sent_time_);
- }
-
- private:
- uint32_t frame_num_;
- uint64_t sent_time_;
- uint64_t received_time_;
-
- uint64_t previous_sent_time_;
- uint64_t previous_received_time_;
- uint32_t size_;
-
- uint32_t received_pkt_m;
- uint32_t burst_size_m;
-};
-
-class CongestionDetection {
- public:
- CongestionDetection();
- ~CongestionDetection();
-
- void addPacket(const core::ContentObject &content_object);
-
- BandwidthUsage getState() { return cc_estimator_.State(); }
-
- void updateStats();
-
- private:
- TrendlineEstimator cc_estimator_;
- std::map<uint32_t, FrameStats> chunks_;
- std::queue<uint32_t> chunks_number_;
-
- FrameStats last_processed_chunk_;
-};
-
-} // end namespace rtc
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/probe_handler.cc b/libtransport/src/protocols/rtc/probe_handler.cc
index efba362d4..abaca6ad9 100644
--- a/libtransport/src/protocols/rtc/probe_handler.cc
+++ b/libtransport/src/protocols/rtc/probe_handler.cc
@@ -43,7 +43,7 @@ uint64_t ProbeHandler::getRtt(uint32_t seq) {
std::chrono::steady_clock::now().time_since_epoch())
.count();
uint64_t rtt = now - it->second;
- if(rtt < 1) rtt = 1;
+ if (rtt < 1) rtt = 1;
pending_probes_.erase(it);
diff --git a/libtransport/src/protocols/rtc/probe_handler.h b/libtransport/src/protocols/rtc/probe_handler.h
index b8ed84445..e34b23df0 100644
--- a/libtransport/src/protocols/rtc/probe_handler.h
+++ b/libtransport/src/protocols/rtc/probe_handler.h
@@ -14,9 +14,8 @@
*/
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <functional>
#include <random>
#include <unordered_map>
@@ -32,8 +31,7 @@ class ProbeHandler : public std::enable_shared_from_this<ProbeHandler> {
using SendProbeCallback = std::function<void(uint32_t)>;
public:
- ProbeHandler(SendProbeCallback &&send_callback,
- asio::io_service &io_service);
+ ProbeHandler(SendProbeCallback &&send_callback, asio::io_service &io_service);
~ProbeHandler();
@@ -53,8 +51,8 @@ class ProbeHandler : public std::enable_shared_from_this<ProbeHandler> {
private:
uint32_t probe_interval_; // us
- uint32_t max_probes_; // packets
- uint32_t sent_probes_; // packets
+ uint32_t max_probes_; // packets
+ uint32_t sent_probes_; // packets
std::unique_ptr<asio::steady_timer> probe_timer_;
diff --git a/libtransport/src/protocols/rtc/rtc.cc b/libtransport/src/protocols/rtc/rtc.cc
index 46659ac74..0cb4cda1d 100644
--- a/libtransport/src/protocols/rtc/rtc.cc
+++ b/libtransport/src/protocols/rtc/rtc.cc
@@ -17,8 +17,11 @@
#include <hicn/transport/interfaces/socket_consumer.h>
#include <implementation/socket_consumer.h>
#include <math.h>
+#include <protocols/errors.h>
+#include <protocols/incremental_indexer_bytestream.h>
#include <protocols/rtc/rtc.h>
#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_indexer.h>
#include <protocols/rtc/rtc_rc_queue.h>
#include <algorithm>
@@ -33,39 +36,41 @@ using namespace interface;
RTCTransportProtocol::RTCTransportProtocol(
implementation::ConsumerSocket *icn_socket)
- : TransportProtocol(icn_socket, nullptr),
- DatagramReassembly(icn_socket, this),
+ : TransportProtocol(icn_socket, new RtcIndexer<>(icn_socket, this),
+ new DatagramReassembly(icn_socket, this)),
number_(0) {
icn_socket->getSocketOption(PORTAL, portal_);
round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
scheduler_timer_ =
std::make_unique<asio::steady_timer>(portal_->getIoService());
+ pacing_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
}
RTCTransportProtocol::~RTCTransportProtocol() {}
void RTCTransportProtocol::resume() {
- if (is_running_) return;
-
- is_running_ = true;
-
newRound();
+ TransportProtocol::resume();
+}
- portal_->runEventsLoop();
- is_running_ = false;
+std::size_t RTCTransportProtocol::transportHeaderLength() {
+ return DATA_HEADER_SIZE +
+ (fec_decoder_ != nullptr ? fec_decoder_->getFecHeaderSize() : 0);
}
// private
void RTCTransportProtocol::initParams() {
- portal_->setConsumerCallback(this);
+ TransportProtocol::reset();
rc_ = std::make_shared<RTCRateControlQueue>();
ldr_ = std::make_shared<RTCLossDetectionAndRecovery>(
+ indexer_verifier_.get(),
std::bind(&RTCTransportProtocol::sendRtxInterest, this,
std::placeholders::_1),
portal_->getIoService());
state_ = std::make_shared<RTCState>(
+ indexer_verifier_.get(),
std::bind(&RTCTransportProtocol::sendProbeInterest, this,
std::placeholders::_1),
std::bind(&RTCTransportProtocol::discoveredRtt, this),
@@ -83,8 +88,27 @@ void RTCTransportProtocol::initParams() {
// Cancel timer
number_++;
round_timer_->cancel();
+
scheduler_timer_->cancel();
scheduler_timer_on_ = false;
+ last_interest_sent_time_ = 0;
+ last_interest_sent_seq_ = 0;
+
+#if 0
+ if(portal_->isConnectedToFwd()){
+ max_aggregated_interest_ = 1;
+ }else{
+ max_aggregated_interest_ = MAX_INTERESTS_IN_BATCH;
+ }
+#else
+ max_aggregated_interest_ = 1;
+#endif
+
+ max_sent_int_ =
+ std::ceil((double)MAX_PACING_BATCH / (double)max_aggregated_interest_);
+
+ pacing_timer_->cancel();
+ pacing_timer_on_ = false;
// delete all timeouts and future nacks
timeouts_or_nacks_.clear();
@@ -93,16 +117,28 @@ void RTCTransportProtocol::initParams() {
current_sync_win_ = INITIAL_WIN;
max_sync_win_ = INITIAL_WIN_MAX;
- // names/packets var
- next_segment_ = 0;
-
socket_->setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
RTC_INTEREST_LIFETIME);
+
+ // FEC
+ using namespace std::placeholders;
+ enableFEC(std::bind(&RTCTransportProtocol::onFecPackets, this, _1),
+ /* We leave the buffer allocation to the fec decoder */
+ fec::FECBase::BufferRequested(0));
+
+ if (fec_decoder_) {
+ indexer_verifier_->enableFec(fec_type_);
+ indexer_verifier_->setNFec(0);
+ ldr_->setFecParams(fec::FECUtils::getBlockSymbols(fec_type_),
+ fec::FECUtils::getSourceSymbols(fec_type_));
+ } else {
+ indexer_verifier_->disableFec();
+ }
}
// private
void RTCTransportProtocol::reset() {
- TRANSPORT_LOGD("reset called");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "reset called";
initParams();
newRound();
}
@@ -113,11 +149,13 @@ void RTCTransportProtocol::inactiveProducer() {
current_sync_win_ = INITIAL_WIN;
max_sync_win_ = INITIAL_WIN_MAX;
- TRANSPORT_LOGD("Current window: %u, max_sync_win_: %u", current_sync_win_,
- max_sync_win_);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Current window: " << current_sync_win_
+ << ", max_sync_win_: " << max_sync_win_;
// names/packets var
- next_segment_ = 0;
+ indexer_verifier_->reset();
+ indexer_verifier_->enableFec(fec_type_);
+ indexer_verifier_->setNFec(0);
ldr_->clear();
}
@@ -137,10 +175,13 @@ void RTCTransportProtocol::newRound() {
uint32_t received_bytes = state_->getReceivedBytesInRound();
uint32_t sent_interest = state_->getSentInterestInRound();
uint32_t lost_data = state_->getLostData();
+ uint32_t definitely_lost = state_->getDefinitelyLostPackets();
uint32_t recovered_losses = state_->getRecoveredLosses();
uint32_t received_nacks = state_->getReceivedNacksInRound();
+ uint32_t received_fec = state_->getReceivedFecPackets();
bool in_sync = (current_state_ == SyncState::in_sync);
+ ldr_->onNewRound(in_sync);
state_->onNewRound((double)ROUND_LEN, in_sync);
rc_->onNewRound((double)ROUND_LEN);
@@ -161,11 +202,13 @@ void RTCTransportProtocol::newRound() {
}
}
- TRANSPORT_LOGD("Calling updateSyncWindow in newRound function");
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Calling updateSyncWindow in newRound function";
updateSyncWindow();
sendStatsToApp(sent_retx, received_bytes, sent_interest, lost_data,
- recovered_losses, received_nacks);
+ definitely_lost, recovered_losses, received_nacks,
+ received_fec);
newRound();
});
}
@@ -173,6 +216,7 @@ void RTCTransportProtocol::newRound() {
void RTCTransportProtocol::discoveredRtt() {
start_send_interest_ = true;
ldr_->turnOnRTX();
+ ldr_->onNewRound(false);
updateSyncWindow();
}
@@ -182,22 +226,23 @@ void RTCTransportProtocol::computeMaxSyncWindow() {
if (production_rate == 0.0 || packet_size == 0.0) {
// the consumer has no info about the producer,
// keep the previous maxCWin
- TRANSPORT_LOGD(
- "Returning in computeMaxSyncWindow because: prod_rate: %d || "
- "packet_size: %d",
- (int)(production_rate == 0.0), (int)(packet_size == 0.0));
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Returning in computeMaxSyncWindow because: prod_rate: "
+ << (production_rate == 0.0)
+ << " || packet_size: " << (packet_size == 0.0);
return;
}
+ production_rate += (production_rate * indexer_verifier_->getMaxFecOverhead());
+
uint32_t lifetime = default_values::interest_lifetime;
socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
lifetime);
double lifetime_ms = (double)lifetime / MILLI_IN_A_SEC;
-
- max_sync_win_ =
- (uint32_t)ceil((production_rate * lifetime_ms *
- INTEREST_LIFETIME_REDUCTION_FACTOR) / packet_size);
+ max_sync_win_ = (uint32_t)ceil(
+ (production_rate * lifetime_ms * INTEREST_LIFETIME_REDUCTION_FACTOR) /
+ packet_size);
max_sync_win_ = std::min(max_sync_win_, rc_->getCongesionWindow());
}
@@ -219,12 +264,25 @@ void RTCTransportProtocol::updateSyncWindow() {
// if some of the info are not available do not update the current win
if (prod_rate != 0.0 && rtt != 0.0 && packet_size != 0.0) {
- current_sync_win_ = (uint32_t)ceil(prod_rate * rtt / packet_size);
- current_sync_win_ += (uint32_t)
- ceil(prod_rate * (PRODUCER_BUFFER_MS / MILLI_IN_A_SEC) / packet_size);
+ double fec_interest_overhead = (double)state_->getPendingFecPackets() /
+ (double)(state_->getPendingInterestNumber() -
+ state_->getPendingFecPackets());
+
+ double fec_overhead =
+ std::max(indexer_verifier_->getFecOverhead(), fec_interest_overhead);
+
+ prod_rate += (prod_rate * fec_overhead);
- if(current_state_ == SyncState::catch_up) {
- current_sync_win_ = (uint32_t) (current_sync_win_ * CATCH_UP_WIN_INCREMENT);
+ current_sync_win_ = (uint32_t)ceil(prod_rate * rtt / packet_size);
+ uint32_t buffer = PRODUCER_BUFFER_MS;
+ if (rtt > 150)
+ buffer = buffer * 2; // if the RTT is too large we increase the
+ // the size of the buffer
+ current_sync_win_ +=
+ ceil(prod_rate * (buffer / MILLI_IN_A_SEC) / packet_size);
+
+ if (current_state_ == SyncState::catch_up) {
+ current_sync_win_ = current_sync_win_ * CATCH_UP_WIN_INCREMENT;
}
current_sync_win_ = std::min(current_sync_win_, max_sync_win_);
@@ -243,70 +301,48 @@ void RTCTransportProtocol::decreaseSyncWindow() {
scheduleNextInterests();
}
-void RTCTransportProtocol::sendInterest(Name *interest_name) {
- TRANSPORT_LOGD("Sending interest for name %s",
- interest_name->toString().c_str());
-
- auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
- interest->setName(*interest_name);
-
- uint32_t lifetime = default_values::interest_lifetime;
- socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
- lifetime);
- interest->setLifetime(uint32_t(lifetime));
-
- if (*on_interest_output_) {
- (*on_interest_output_)(*socket_->getInterface(), *interest);
- }
-
- if (TRANSPORT_EXPECT_FALSE(!is_running_ && !is_first_)) {
- return;
- }
-
- portal_->sendInterest(std::move(interest));
-}
-
void RTCTransportProtocol::sendRtxInterest(uint32_t seq) {
- if (!is_running_ && !is_first_) return;
+ if (!isRunning() && !is_first_) return;
- if(!start_send_interest_) return;
+ if (!start_send_interest_) return;
Name *interest_name = nullptr;
socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
&interest_name);
- TRANSPORT_LOGD("send rtx %u", seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "send rtx " << seq;
interest_name->setSuffix(seq);
- sendInterest(interest_name);
+ sendInterest(*interest_name);
}
void RTCTransportProtocol::sendProbeInterest(uint32_t seq) {
- if (!is_running_ && !is_first_) return;
+ if (!isRunning() && !is_first_) return;
Name *interest_name = nullptr;
socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
&interest_name);
- TRANSPORT_LOGD("send probe %u", seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "send probe " << seq;
interest_name->setSuffix(seq);
- sendInterest(interest_name);
+ sendInterest(*interest_name);
}
void RTCTransportProtocol::scheduleNextInterests() {
- TRANSPORT_LOGD("Schedule next interests");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Schedule next interests";
- if (!is_running_ && !is_first_) return;
+ if (!isRunning() && !is_first_) return;
- if(!start_send_interest_) return; // RTT discovering phase is not finished so
- // do not start to send interests
+ if (pacing_timer_on_) return; // wait pacing timer for the next send
- if (scheduler_timer_on_) return; // wait befor send other interests
+ if (!start_send_interest_)
+ return; // RTT discovering phase is not finished so
+ // do not start to send interests
if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive())) {
- TRANSPORT_LOGD("Inactive producer.");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Inactive producer.";
// here we keep seding the same interest until the producer
// does not start again
- if (next_segment_ != 0) {
+ if (indexer_verifier_->checkNextSuffix() != 0) {
// the producer just become inactive, reset the state
inactiveProducer();
}
@@ -315,125 +351,208 @@ void RTCTransportProtocol::scheduleNextInterests() {
socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
&interest_name);
- TRANSPORT_LOGD("send interest %u", next_segment_);
- interest_name->setSuffix(next_segment_);
+ uint32_t next_seg = 0;
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "send interest " << next_seg;
+ interest_name->setSuffix(next_seg);
if (portal_->interestIsPending(*interest_name)) {
// if interest 0 is already pending we return
return;
}
- sendInterest(interest_name);
+ sendInterest(*interest_name);
state_->onSendNewInterest(interest_name);
return;
}
- TRANSPORT_LOGD("Pending interest number: %d -- current_sync_win_: %d",
- state_->getPendingInterestNumber(), current_sync_win_);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Pending interest number: " << state_->getPendingInterestNumber()
+ << " -- current_sync_win_: " << current_sync_win_;
+
+ uint32_t pending = state_->getPendingInterestNumber();
+ if (pending >= current_sync_win_) return; // no space in the window
+
+ if ((current_sync_win_ - pending) < max_aggregated_interest_) {
+ if (scheduler_timer_on_) return; // timer already scheduled
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ uint64_t time = now - last_interest_sent_time_;
+ if (time < WAIT_FOR_INTEREST_BATCH) {
+ uint64_t next = WAIT_FOR_INTEREST_BATCH - time;
+ scheduler_timer_on_ = true;
+ scheduler_timer_->expires_from_now(std::chrono::milliseconds(next));
+ scheduler_timer_->async_wait([this](std::error_code ec) {
+ if (ec) return;
+ if (!scheduler_timer_on_) return;
+
+ scheduler_timer_on_ = false;
+ scheduleNextInterests();
+ });
+ return; // whait for the timer
+ }
+ }
+
+ scheduler_timer_on_ = false;
+ scheduler_timer_->cancel();
// skip nacked pacekts
- if (next_segment_ <= state_->getLastSeqNacked()) {
- next_segment_ = state_->getLastSeqNacked() + 1;
+ if (indexer_verifier_->checkNextSuffix() <= state_->getLastSeqNacked()) {
+ indexer_verifier_->jumpToIndex(state_->getLastSeqNacked() + 1);
}
// skipe received packets
- if (next_segment_ <= state_->getHighestSeqReceivedInOrder()) {
- next_segment_ = state_->getHighestSeqReceivedInOrder() + 1;
+ if (indexer_verifier_->checkNextSuffix() <=
+ state_->getHighestSeqReceivedInOrder()) {
+ indexer_verifier_->jumpToIndex(state_->getHighestSeqReceivedInOrder() + 1);
}
uint32_t sent_interests = 0;
+ uint32_t sent_packets = 0;
+ uint32_t aggregated_counter = 0;
+ Name *name = nullptr;
+ Name interest_name;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
+ std::array<uint32_t, MAX_AGGREGATED_INTEREST> additional_suffixes;
+
while ((state_->getPendingInterestNumber() < current_sync_win_) &&
- (sent_interests < MAX_INTERESTS_IN_BATCH)) {
- TRANSPORT_LOGD("In while loop. Window size: %u", current_sync_win_);
- Name *interest_name = nullptr;
- socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
- &interest_name);
+ (sent_interests < max_sent_int_)) {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "In while loop. Window size: " << current_sync_win_;
+
+ uint32_t next_seg = indexer_verifier_->getNextSuffix();
- interest_name->setSuffix(next_segment_);
+ name->setSuffix(next_seg);
// send the packet only if:
// 1) it is not pending yet (not true for rtx)
// 2) the packet is not received or lost
// 3) is not in the rtx list
- if (portal_->interestIsPending(*interest_name) ||
- state_->isReceivedOrLost(next_segment_) != PacketState::UNKNOWN ||
- ldr_->isRtx(next_segment_)) {
- TRANSPORT_LOGD(
- "skip interest %u because: pending %u, recv %u, rtx %u",
- next_segment_, (portal_->interestIsPending(*interest_name)),
- (state_->isReceivedOrLost(next_segment_) != PacketState::UNKNOWN),
- (ldr_->isRtx(next_segment_)));
- next_segment_ = (next_segment_ + 1) % MIN_PROBE_SEQ;
+ // 4) is fec and is not in order (!= last sent + 1)
+ if (portal_->interestIsPending(*name) ||
+ state_->isReceivedOrLost(next_seg) != PacketState::UNKNOWN ||
+ ldr_->isRtx(next_seg) ||
+ (indexer_verifier_->isFec(next_seg) &&
+ next_seg != last_interest_sent_seq_ + 1)) {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "skip interest " << next_seg << " because: pending "
+ << portal_->interestIsPending(*name) << ", recv "
+ << (state_->isReceivedOrLost(next_seg) != PacketState::UNKNOWN)
+ << ", rtx " << (ldr_->isRtx(next_seg)) << ", is old fec "
+ << ((indexer_verifier_->isFec(next_seg) &&
+ next_seg != last_interest_sent_seq_ + 1));
continue;
}
+ if (aggregated_counter == 0) {
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "(name) send interest " << next_seg;
+ interest_name = *name;
+ } else {
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "(append) send interest " << next_seg;
+ additional_suffixes[aggregated_counter - 1] = next_seg;
+ }
- sent_interests++;
- TRANSPORT_LOGD("send interest %u", next_segment_);
- sendInterest(interest_name);
- state_->onSendNewInterest(interest_name);
+ last_interest_sent_seq_ = next_seg;
+ state_->onSendNewInterest(name);
+ aggregated_counter++;
+
+ if (aggregated_counter >= max_aggregated_interest_) {
+ sent_packets++;
+ sent_interests++;
+ sendInterest(interest_name, &additional_suffixes, aggregated_counter - 1);
+ last_interest_sent_time_ =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ aggregated_counter = 0;
+ }
+ }
- next_segment_ = (next_segment_ + 1) % MIN_PROBE_SEQ;
+ // exiting the while we may have some pending interest to send
+ if (aggregated_counter != 0) {
+ sent_packets++;
+ last_interest_sent_time_ =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ sendInterest(interest_name, &additional_suffixes, aggregated_counter - 1);
}
if (state_->getPendingInterestNumber() < current_sync_win_) {
- // we still have space in the window but we already sent a batch of
- // MAX_INTERESTS_IN_BATCH interest. for the following ones wait one
- // WAIT_BETWEEN_INTEREST_BATCHES to avoid local packets drop
+ // we still have space in the window but we already sent too many packets
+ // wait PACING_WAIT to avoid drops in the kernel
- scheduler_timer_on_ = true;
- scheduler_timer_->expires_from_now(
- std::chrono::microseconds(WAIT_BETWEEN_INTEREST_BATCHES));
+ pacing_timer_on_ = true;
+ pacing_timer_->expires_from_now(std::chrono::microseconds(PACING_WAIT));
scheduler_timer_->async_wait([this](std::error_code ec) {
if (ec) return;
- if (!scheduler_timer_on_) return;
+ if (!pacing_timer_on_) return;
- scheduler_timer_on_ = false;
+ pacing_timer_on_ = false;
scheduleNextInterests();
});
}
}
-void RTCTransportProtocol::onTimeout(Interest::Ptr &&interest) {
- uint32_t segment_number = interest->getName().getSuffix();
-
- TRANSPORT_LOGD("timeout for packet %u", segment_number);
+void RTCTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
+ const Name &name) {
+ uint32_t segment_number = name.getSuffix();
if (segment_number >= MIN_PROBE_SEQ) {
// this is a timeout on a probe, do nothing
return;
}
+ PacketState state = state_->isReceivedOrLost(segment_number);
+ if (state != PacketState::UNKNOWN) {
+ // we may recover a packets using fec, ignore this timer
+ return;
+ }
+
timeouts_or_nacks_.insert(segment_number);
if (TRANSPORT_EXPECT_TRUE(state_->isProducerActive()) &&
- segment_number <= state_->getHighestSeqReceivedInOrder()) {
+ segment_number <= state_->getHighestSeqReceived()) {
// we retransmit packets only if the producer is active, otherwise we
// use timeouts to avoid to send too much traffic
//
// a timeout is sent using RTX only if it is an old packet. if it is for a
// seq number that we didn't reach yet, we send the packet using the normal
// schedule next interest
- TRANSPORT_LOGD("handle timeout for packet %u using rtx", segment_number);
- ldr_->onTimeout(segment_number);
- state_->onTimeout(segment_number);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "handle timeout for packet " << segment_number << " using rtx";
+ if (ldr_->isRtxOn()) {
+ ldr_->onTimeout(segment_number);
+ if (indexer_verifier_->isFec(segment_number))
+ state_->onTimeout(segment_number, true);
+ else
+ state_->onTimeout(segment_number, false);
+ } else {
+ // in this case we wil never recover the timeout
+ state_->onTimeout(segment_number, true);
+ }
scheduleNextInterests();
return;
}
- TRANSPORT_LOGD("handle timeout for packet %u using normal interests",
- segment_number);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "handle timeout for packet " << segment_number
+ << " using normal interests";
- if (segment_number < next_segment_) {
+ if (segment_number < indexer_verifier_->checkNextSuffix()) {
// this is a timeout for a packet that will be generated in the future but
// we are asking for higher sequence numbers. we need to go back like in the
// case of future nacks
- TRANSPORT_LOGD("on timeout next seg = %u, jump to %u",
- next_segment_, segment_number);
- next_segment_ = segment_number;
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "On timeout next seg = " << indexer_verifier_->checkNextSuffix()
+ << ", jump to " << segment_number;
+ // add an extra space in the window
+ current_sync_win_++;
+ indexer_verifier_->jumpToIndex(segment_number);
}
- state_->onTimeout(segment_number);
+ state_->onTimeout(segment_number, false);
scheduleNextInterests();
}
@@ -446,8 +565,8 @@ void RTCTransportProtocol::onNack(const ContentObject &content_object) {
// check if the packet got a timeout
- TRANSPORT_LOGD("Nack received %u. Production segment: %u", nack_segment,
- production_seg);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Nack received " << nack_segment
+ << ". Production segment: " << production_seg;
bool compute_stats = true;
auto tn_it = timeouts_or_nacks_.find(nack_segment);
@@ -459,14 +578,15 @@ void RTCTransportProtocol::onNack(const ContentObject &content_object) {
state_->onNackPacketReceived(content_object, compute_stats);
ldr_->onNackPacketReceived(content_object);
- // both in case of past and future nack we set next_segment_ equal to the
+ // both in case of past and future nack we jump to the
// production segment in the nack. In case of past nack we will skip unneded
// interest (this is already done in the scheduleNextInterest in any case)
// while in case of future nacks we can go back in time and ask again for the
// content that generated the nack
- TRANSPORT_LOGD("on nack next seg = %u, jump to %u",
- next_segment_, production_seg);
- next_segment_ = production_seg;
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "On nack next seg = " << indexer_verifier_->checkNextSuffix()
+ << ", jump to " << production_seg;
+ indexer_verifier_->jumpToIndex(production_seg);
if (production_seg > nack_segment) {
// remove the nack is it exists
@@ -496,30 +616,33 @@ void RTCTransportProtocol::onNack(const ContentObject &content_object) {
void RTCTransportProtocol::onProbe(const ContentObject &content_object) {
bool valid = state_->onProbePacketReceived(content_object);
- if(!valid) return;
+ if (!valid) return;
struct nack_packet_t *probe =
(struct nack_packet_t *)content_object.getPayload()->data();
uint32_t production_seg = probe->getProductionSegement();
- // as for the nacks set next_segment_
- TRANSPORT_LOGD("on probe next seg = %u, jump to %u",
- next_segment_, production_seg);
- next_segment_ = production_seg;
+ // as for the nacks set next_segment
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "on probe next seg = " << indexer_verifier_->checkNextSuffix()
+ << ", jump to " << production_seg;
+ indexer_verifier_->jumpToIndex(production_seg);
ldr_->onProbePacketReceived(content_object);
updateSyncWindow();
}
-void RTCTransportProtocol::onContentObject(Interest &interest,
- ContentObject &content_object) {
- TRANSPORT_LOGD("Received content object of size: %zu",
- content_object.payloadSize());
- uint32_t payload_size = (uint32_t) content_object.payloadSize();
+void RTCTransportProtocol::onContentObjectReceived(
+ Interest &interest, ContentObject &content_object, std::error_code &ec) {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Received content object of size: " << content_object.payloadSize();
+ uint32_t payload_size = content_object.payloadSize();
uint32_t segment_number = content_object.getName().getSuffix();
+ ec = make_error_code(protocol_error::not_reassemblable);
+
if (segment_number >= MIN_PROBE_SEQ) {
- TRANSPORT_LOGD("Received probe %u", segment_number);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received probe " << segment_number;
if (*on_content_object_input_) {
(*on_content_object_input_)(*socket_->getInterface(), content_object);
}
@@ -528,7 +651,7 @@ void RTCTransportProtocol::onContentObject(Interest &interest,
}
if (payload_size == NACK_HEADER_SIZE) {
- TRANSPORT_LOGD("Received nack %u", segment_number);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received nack " << segment_number;
if (*on_content_object_input_) {
(*on_content_object_input_)(*socket_->getInterface(), content_object);
}
@@ -536,9 +659,8 @@ void RTCTransportProtocol::onContentObject(Interest &interest,
return;
}
- TRANSPORT_LOGD("Received content %u", segment_number);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received content " << segment_number;
- rc_->onDataPacketReceived(content_object);
bool compute_stats = true;
auto tn_it = timeouts_or_nacks_.find(segment_number);
if (tn_it != timeouts_or_nacks_.end()) {
@@ -551,25 +673,49 @@ void RTCTransportProtocol::onContentObject(Interest &interest,
// check if the packet was already received
PacketState state = state_->isReceivedOrLost(segment_number);
- state_->onDataPacketReceived(content_object, compute_stats);
- ldr_->onDataPacketReceived(content_object);
- // if the stat for this seq number is received do not send the packet to app
if (state != PacketState::RECEIVED) {
- if (*on_content_object_input_) {
- (*on_content_object_input_)(*socket_->getInterface(), content_object);
+ // send packet to decoder
+ if (fec_decoder_) {
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "send packet " << segment_number << " to FEC decoder";
+ fec_decoder_->onDataPacket(
+ content_object, content_object.headerSize() + rtc::DATA_HEADER_SIZE);
+ }
+ if (!indexer_verifier_->isFec(segment_number)) {
+ // the packet may be alredy sent to the ap by the decoder, check again if
+ // it is already received
+ state = state_->isReceivedOrLost(segment_number);
+ if (state != PacketState::RECEIVED) {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Received content " << segment_number;
+
+ state_->onDataPacketReceived(content_object, compute_stats);
+
+ if (*on_content_object_input_) {
+ (*on_content_object_input_)(*socket_->getInterface(), content_object);
+ }
+ ec = make_error_code(protocol_error::success);
+ }
+ } else {
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "Received fec " << segment_number;
+ state_->onFecPacketReceived(content_object);
}
- reassemble(content_object);
} else {
- TRANSPORT_LOGD("Received duplicated content %u, drop it", segment_number);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Received duplicated content " << segment_number << ", drop it";
+ ec = make_error_code(protocol_error::duplicated_content);
}
+ ldr_->onDataPacketReceived(content_object);
+ rc_->onDataPacketReceived(content_object);
+
updateSyncWindow();
}
void RTCTransportProtocol::sendStatsToApp(
uint32_t retx_count, uint32_t received_bytes, uint32_t sent_interests,
- uint32_t lost_data, uint32_t recovered_losses, uint32_t received_nacks) {
+ uint32_t lost_data, uint32_t definitely_lost, uint32_t recovered_losses,
+ uint32_t received_nacks, uint32_t received_fec) {
if (*stats_summary_) {
// Send the stats to the app
stats_->updateQueuingDelay(state_->getQueuing());
@@ -581,23 +727,35 @@ void RTCTransportProtocol::sendStatsToApp(
stats_->updateBytesRecv(received_bytes);
stats_->updateInterestTx(sent_interests);
stats_->updateReceivedNacks(received_nacks);
+ stats_->updateReceivedFEC(received_fec);
stats_->updateAverageWindowSize(current_sync_win_);
stats_->updateLossRatio(state_->getLossRate());
stats_->updateAverageRtt(state_->getRTT());
+ stats_->updateQueuingDelay(state_->getQueuing());
stats_->updateLostData(lost_data);
+ stats_->updateDefinitelyLostData(definitely_lost);
stats_->updateRecoveredData(recovered_losses);
stats_->updateCCState((unsigned int)current_state_ ? 1 : 0);
(*stats_summary_)(*socket_->getInterface(), *stats_);
}
}
-void RTCTransportProtocol::reassemble(ContentObject &content_object) {
- auto read_buffer = content_object.getPayload();
- TRANSPORT_LOGD("Size of payload: %zu", read_buffer->length());
- read_buffer->trimStart(DATA_HEADER_SIZE);
- Reassembly::read_buffer_ = std::move(read_buffer);
- Reassembly::notifyApplication();
+void RTCTransportProtocol::onFecPackets(
+ std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
+ for (auto &packet : packets) {
+ PacketState state = state_->isReceivedOrLost(packet.first);
+ if (state != PacketState::RECEIVED) {
+ state_->onPacketRecoveredFec(packet.first);
+ ldr_->onPacketRecoveredFec(packet.first);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Recovered packet " << packet.first << " through FEC.";
+ reassembly_->reassemble(*packet.second, packet.first);
+ } else {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Packet" << packet.first << "already received.";
+ }
+ }
}
} // end namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc.h b/libtransport/src/protocols/rtc/rtc.h
index 596887067..e6431264d 100644
--- a/libtransport/src/protocols/rtc/rtc.h
+++ b/libtransport/src/protocols/rtc/rtc.h
@@ -30,8 +30,7 @@ namespace protocol {
namespace rtc {
-class RTCTransportProtocol : public TransportProtocol,
- public DatagramReassembly {
+class RTCTransportProtocol : public TransportProtocol {
public:
RTCTransportProtocol(implementation::ConsumerSocket *icnet_socket);
@@ -43,6 +42,8 @@ class RTCTransportProtocol : public TransportProtocol,
void resume() override;
+ std::size_t transportHeaderLength() override;
+
private:
enum class SyncState { catch_up = 0, in_sync = 1, last };
@@ -63,24 +64,28 @@ class RTCTransportProtocol : public TransportProtocol,
void decreaseSyncWindow();
// packet functions
- void sendInterest(Name *interest_name);
void sendRtxInterest(uint32_t seq);
void sendProbeInterest(uint32_t seq);
void scheduleNextInterests() override;
- void onTimeout(Interest::Ptr &&interest) override;
+ void onInterestTimeout(Interest::Ptr &interest, const Name &name) override;
void onNack(const ContentObject &content_object);
void onProbe(const ContentObject &content_object);
- void reassemble(ContentObject &content_object) override;
- void onContentObject(Interest &interest,
- ContentObject &content_object) override;
- void onPacketDropped(Interest &interest,
- ContentObject &content_object) override {}
+ void onContentObjectReceived(Interest &interest,
+ ContentObject &content_object,
+ std::error_code &ec) override;
+ void onPacketDropped(Interest &interest, ContentObject &content_object,
+ const std::error_code &reason) override {}
void onReassemblyFailed(std::uint32_t missing_segment) override {}
// interaction with app functions
void sendStatsToApp(uint32_t retx_count, uint32_t received_bytes,
uint32_t sent_interests, uint32_t lost_data,
- uint32_t recovered_losses, uint32_t received_nacks);
+ uint32_t definitely_lost, uint32_t recovered_losses,
+ uint32_t received_nacks, uint32_t received_fec);
+
+ // FEC functions
+ void onFecPackets(std::vector<std::pair<uint32_t, fec::buffer>> &packets);
+
// protocol state
bool start_send_interest_;
SyncState current_state_;
@@ -88,17 +93,30 @@ class RTCTransportProtocol : public TransportProtocol,
uint32_t current_sync_win_;
uint32_t max_sync_win_;
- // controller var
+ // round timer
std::unique_ptr<asio::steady_timer> round_timer_;
+
+ // scheduler timer (postpone interest sending to explot aggregated interests)
std::unique_ptr<asio::steady_timer> scheduler_timer_;
bool scheduler_timer_on_;
+ uint64_t last_interest_sent_time_;
+ uint64_t last_interest_sent_seq_;
+
+ // maximum aggregated interest. if the transport is connected to the forwarder
+ // we cannot use aggregated interests
+ uint32_t max_aggregated_interest_;
+ // maximum number of intereset that can be sent in a loop to avoid packets
+ // dropped by the kernel
+ uint32_t max_sent_int_;
+
+ // pacing timer (do not send too many interests in a short time to avoid
+ // packet drops in the kernel)
+ std::unique_ptr<asio::steady_timer> pacing_timer_;
+ bool pacing_timer_on_;
// timeouts
std::unordered_set<uint32_t> timeouts_or_nacks_;
- // names/packets var
- uint32_t next_segment_;
-
std::shared_ptr<RTCState> state_;
std::shared_ptr<RTCRateControl> rc_;
std::shared_ptr<RTCLossDetectionAndRecovery> ldr_;
diff --git a/libtransport/src/protocols/rtc/rtc_consts.h b/libtransport/src/protocols/rtc/rtc_consts.h
index e172fc7a1..d04bc1b1f 100644
--- a/libtransport/src/protocols/rtc/rtc_consts.h
+++ b/libtransport/src/protocols/rtc/rtc_consts.h
@@ -37,12 +37,26 @@ const double INTEREST_LIFETIME_REDUCTION_FACTOR = 0.8;
const uint32_t PRODUCER_BUFFER_MS = 200; // ms
// interest scheduler
-const uint32_t MAX_INTERESTS_IN_BATCH = 5;
-const uint32_t WAIT_BETWEEN_INTEREST_BATCHES = 1000; // usec
+// const uint32_t MAX_INTERESTS_IN_BATCH = 5;
+// const uint32_t WAIT_BETWEEN_INTEREST_BATCHES = 1000; // usec
+const uint32_t MAX_INTERESTS_IN_BATCH = 5; // number of seq numbers per
+ // aggregated interest packet
+ // considering the name itself
+const uint32_t WAIT_FOR_INTEREST_BATCH = 20; // msec. timer that we wait to try
+ // to aggregate interest in the
+ // same packet
+const uint32_t MAX_PACING_BATCH = 5;
+// number of interest that we can send inside
+// the loop before they get dropped by the
+// kernel.
+const uint32_t PACING_WAIT = 1000; // usec to wait betwing two pacing batch. As
+ // for MAX_PACING_BATCH this value was
+ // computed during tests
+const uint32_t MAX_RTX_IN_BATCH = 10; // max rtx to send in loop
// packet const
const uint32_t HICN_HEADER_SIZE = 40 + 20; // IPv6 + TCP bytes
-const uint32_t RTC_INTEREST_LIFETIME = 1000;
+const uint32_t RTC_INTEREST_LIFETIME = 2000;
// probes sequence range
const uint32_t MIN_PROBE_SEQ = 0xefffffff;
@@ -51,19 +65,18 @@ const uint32_t MAX_RTT_PROBE_SEQ = 0xffffffff - 1;
// RTT_PROBE_INTERVAL will be used during the section while
// INIT_RTT_PROBE_INTERVAL is used at the beginning to
// quickily estimate the RTT
-const uint32_t RTT_PROBE_INTERVAL = 200000; // us
-const uint32_t INIT_RTT_PROBE_INTERVAL = 500; // us
-const uint32_t INIT_RTT_PROBES = 40; // number of probes to init RTT
+const uint32_t RTT_PROBE_INTERVAL = 200000; // us
+const uint32_t INIT_RTT_PROBE_INTERVAL = 500; // us
+const uint32_t INIT_RTT_PROBES = 40; // number of probes to init RTT
// if the produdcer is not yet started we need to probe multple times
// to get an answer. we wait 100ms between each try
-const uint32_t INIT_RTT_PROBE_RESTART = 100; // ms
+const uint32_t INIT_RTT_PROBE_RESTART = 100; // ms
// once we get the first probe we wait at most 60ms for the others
-const uint32_t INIT_RTT_PROBE_WAIT = 30; // ms
+const uint32_t INIT_RTT_PROBE_WAIT = 30; // ms
// we reuires at least 5 probes to be recevied
-const uint32_t INIT_RTT_MIN_PROBES_TO_RECV = 5; //ms
+const uint32_t INIT_RTT_MIN_PROBES_TO_RECV = 5; // ms
const uint32_t MAX_PENDING_PROBES = 10;
-
// congestion
const double MAX_QUEUING_DELAY = 100.0; // ms
@@ -97,7 +110,7 @@ const double MAX_CACHED_PACKETS = 262144; // 2^18
// about 50 sec of traffic at 50Mbps
// with 1200 bytes packets
-const uint32_t MAX_ROUND_WHIOUT_PACKETS = (const uint32_t)
+const uint32_t MAX_ROUND_WHIOUT_PACKETS =
(20 * MILLI_IN_A_SEC) / ROUND_LEN; // 20 sec in rounds;
// used in ldr
diff --git a/libtransport/src/protocols/rtc/rtc_data_path.cc b/libtransport/src/protocols/rtc/rtc_data_path.cc
index a545225cb..c098088a3 100644
--- a/libtransport/src/protocols/rtc/rtc_data_path.cc
+++ b/libtransport/src/protocols/rtc/rtc_data_path.cc
@@ -69,7 +69,7 @@ void RTCDataPath::insertOwdSample(int64_t owd) {
if (avg_owd != DBL_MAX)
avg_owd = (avg_owd * (1 - ALPHA_RTC)) + (owd * ALPHA_RTC);
else {
- avg_owd = (double)owd;
+ avg_owd = owd;
}
int64_t queueVal = owd - std::min(getMinOwd(), min_owd);
@@ -77,7 +77,7 @@ void RTCDataPath::insertOwdSample(int64_t owd) {
if (queuing_delay != DBL_MAX)
queuing_delay = (queuing_delay * (1 - ALPHA_RTC)) + (queueVal * ALPHA_RTC);
else {
- queuing_delay = (double)queueVal;
+ queuing_delay = queueVal;
}
// keep track of the jitter computed as for RTP (RFC 3550)
@@ -100,7 +100,7 @@ void RTCDataPath::computeInterArrivalGap(uint32_t segment_number) {
largest_recv_seq_ = segment_number;
largest_recv_seq_time_ = now;
if (avg_inter_arrival_ == DBL_MAX)
- avg_inter_arrival_ = (double)delta;
+ avg_inter_arrival_ = delta;
else
avg_inter_arrival_ =
(avg_inter_arrival_ * (1 - ALPHA_RTC)) + (delta * ALPHA_RTC);
diff --git a/libtransport/src/protocols/rtc/rtc_indexer.h b/libtransport/src/protocols/rtc/rtc_indexer.h
new file mode 100644
index 000000000..4aee242bb
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_indexer.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <protocols/errors.h>
+#include <protocols/fec_utils.h>
+#include <protocols/indexer.h>
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/transport_protocol.h>
+
+#include <deque>
+
+namespace transport {
+
+namespace interface {
+class ConsumerSocket;
+}
+
+namespace protocol {
+
+namespace rtc {
+
+template <uint32_t LIMIT = MIN_PROBE_SEQ>
+class RtcIndexer : public Indexer {
+ public:
+ RtcIndexer(implementation::ConsumerSocket *icn_socket,
+ TransportProtocol *transport)
+ : Indexer(icn_socket, transport),
+ first_suffix_(1),
+ next_suffix_(first_suffix_),
+ fec_type_(fec::FECType::UNKNOWN),
+ n_fec_(0),
+ n_current_fec_(n_fec_) {}
+
+ RtcIndexer(RtcIndexer &&other) : Indexer(std::forward<Indexer>(other)) {}
+
+ ~RtcIndexer() {}
+
+ void reset() override {
+ next_suffix_ = first_suffix_;
+ n_fec_ = 0;
+ }
+
+ uint32_t checkNextSuffix() override { return next_suffix_; }
+
+ uint32_t getNextSuffix() override {
+ if (isFec(next_suffix_)) {
+ if (n_current_fec_) {
+ auto ret = next_suffix_++;
+ n_current_fec_--;
+ return ret;
+ } else {
+ n_current_fec_ = n_fec_;
+ next_suffix_ = nextSource(next_suffix_);
+ }
+ } else if (!n_current_fec_) {
+ n_current_fec_ = n_fec_;
+ }
+
+ return (next_suffix_++ % LIMIT);
+ }
+
+ void setFirstSuffix(uint32_t suffix) override {
+ first_suffix_ = suffix % LIMIT;
+ }
+
+ uint32_t getFirstSuffix() override { return first_suffix_; }
+
+ uint32_t jumpToIndex(uint32_t index) override {
+ next_suffix_ = index % LIMIT;
+ return next_suffix_;
+ }
+
+ void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object,
+ bool reassembly) override {
+ setVerifier();
+ auto ret = verifier_->verifyPackets(&content_object);
+
+ switch (ret) {
+ case auth::VerificationPolicy::ACCEPT: {
+ if (reassembly) {
+ reassembly_->reassemble(content_object);
+ }
+ break;
+ }
+
+ case auth::VerificationPolicy::UNKNOWN:
+ case auth::VerificationPolicy::DROP: {
+ transport_->onPacketDropped(
+ interest, content_object,
+ make_error_code(protocol_error::verification_failed));
+ break;
+ }
+
+ case auth::VerificationPolicy::ABORT: {
+ transport_->onContentReassembled(
+ make_error_code(protocol_error::session_aborted));
+ break;
+ }
+ }
+ }
+
+ /**
+ * Retrieve the next segment to be reassembled.
+ */
+ uint32_t getNextReassemblySegment() override {
+ throw errors::RuntimeException(
+ "Get reassembly segment called on rtc indexer. RTC indexer does not "
+ "provide "
+ "reassembly.");
+ }
+
+ bool isFinalSuffixDiscovered() override { return true; }
+
+ uint32_t getFinalSuffix() override { return LIMIT; }
+
+ void enableFec(fec::FECType fec_type) override { fec_type_ = fec_type; }
+
+ void disableFec() override { fec_type_ = fec::FECType::UNKNOWN; }
+
+ void setNFec(uint32_t n_fec) override {
+ n_fec_ = n_fec;
+ n_current_fec_ = n_fec_;
+ }
+
+ uint32_t getNFec() override { return n_fec_; }
+
+ bool isFec(uint32_t index) override {
+ return isFec(fec_type_, index, first_suffix_);
+ }
+
+ double getFecOverhead() override {
+ if (fec_type_ == fec::FECType::UNKNOWN) {
+ return 0;
+ }
+
+ double k = (double)fec::FECUtils::getSourceSymbols(fec_type_);
+ return (double)n_fec_ / k;
+ }
+
+ double getMaxFecOverhead() override {
+ if (fec_type_ == fec::FECType::UNKNOWN) {
+ return 0;
+ }
+
+ double k = (double)fec::FECUtils::getSourceSymbols(fec_type_);
+ double n = (double)fec::FECUtils::getBlockSymbols(fec_type_);
+ return (double)(n - k) / k;
+ }
+
+ static bool isFec(fec::FECType fec_type, uint32_t index,
+ uint32_t first_suffix) {
+ if (index < LIMIT) {
+ return fec::FECUtils::isFec(fec_type, index, first_suffix);
+ }
+
+ return false;
+ }
+
+ static uint32_t nextSource(fec::FECType fec_type, uint32_t index,
+ uint32_t first_suffix) {
+ return fec::FECUtils::nextSource(fec_type, index, first_suffix) % LIMIT;
+ }
+
+ private:
+ uint32_t nextSource(uint32_t index) {
+ return nextSource(fec_type_, index, first_suffix_);
+ }
+
+ private:
+ uint32_t first_suffix_;
+ uint32_t next_suffix_;
+ fec::FECType fec_type_;
+ bool fec_enabled_;
+ uint32_t n_fec_;
+ uint32_t n_current_fec_;
+};
+
+} // namespace rtc
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.cc b/libtransport/src/protocols/rtc/rtc_ldr.cc
index 0ef381fe1..f0de48871 100644
--- a/libtransport/src/protocols/rtc/rtc_ldr.cc
+++ b/libtransport/src/protocols/rtc/rtc_ldr.cc
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <protocols/rtc/rtc_consts.h>
#include <protocols/rtc/rtc_ldr.h>
@@ -26,11 +27,13 @@ namespace protocol {
namespace rtc {
RTCLossDetectionAndRecovery::RTCLossDetectionAndRecovery(
- SendRtxCallback &&callback, asio::io_service &io_service)
+ Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service)
: rtx_on_(false),
+ fec_on_(false),
next_rtx_timer_(MAX_TIMER_RTX),
last_event_(0),
sentinel_timer_interval_(MAX_TIMER_RTX),
+ indexer_(indexer),
send_rtx_callback_(std::move(callback)) {
timer_ = std::make_unique<asio::steady_timer>(io_service);
sentinel_timer_ = std::make_unique<asio::steady_timer>(io_service);
@@ -40,7 +43,7 @@ RTCLossDetectionAndRecovery::~RTCLossDetectionAndRecovery() {}
void RTCLossDetectionAndRecovery::turnOnRTX() {
rtx_on_ = true;
- scheduleSentinelTimer((uint32_t)(state_->getRTT() * CATCH_UP_RTT_INCREMENT));
+ scheduleSentinelTimer(state_->getRTT() * CATCH_UP_RTT_INCREMENT);
}
void RTCLossDetectionAndRecovery::turnOffRTX() {
@@ -48,6 +51,54 @@ void RTCLossDetectionAndRecovery::turnOffRTX() {
clear();
}
+uint32_t RTCLossDetectionAndRecovery::computeFecPacketsToAsk(bool in_sync) {
+ uint32_t current_fec = indexer_->getNFec();
+ double current_loss_rate = state_->getLossRate();
+ double last_loss_rate = state_->getLastRoundLossRate();
+
+ // when in sync ask for fec only if there are losses for 2 rounds
+ if (in_sync && current_fec == 0 &&
+ (current_loss_rate == 0 || last_loss_rate == 0))
+ return 0;
+
+ double loss_rate = state_->getMaxLossRate() * 1.5;
+
+ if (!in_sync && loss_rate == 0) loss_rate = 0.05;
+ if (loss_rate > 0.5) loss_rate = 0.5;
+
+ double exp_losses = (double)k_ * loss_rate;
+ uint32_t fec_to_ask = ceil(exp_losses / (1 - loss_rate));
+
+ if (fec_to_ask > (n_ - k_)) fec_to_ask = n_ - k_;
+
+ return fec_to_ask;
+}
+
+void RTCLossDetectionAndRecovery::onNewRound(bool in_sync) {
+ uint64_t rtt = state_->getRTT();
+ if (!fec_on_ && rtt >= 100) {
+ // turn on fec, here we may have no info so ask for all packets
+ fec_on_ = true;
+ turnOffRTX();
+ indexer_->setNFec(computeFecPacketsToAsk(in_sync));
+ return;
+ }
+
+ if (fec_on_ && rtt > 80) {
+ // keep using fec, maybe update it
+ indexer_->setNFec(computeFecPacketsToAsk(in_sync));
+ return;
+ }
+
+ if ((fec_on_ && rtt <= 80) || (!rtx_on_ && rtt <= 100)) {
+ // turn on rtx
+ fec_on_ = false;
+ indexer_->setNFec(0);
+ turnOnRTX();
+ return;
+ }
+}
+
void RTCLossDetectionAndRecovery::onTimeout(uint32_t seq) {
// always add timeouts to the RTX list to avoid to send the same packet as if
// it was not a rtx
@@ -55,17 +106,23 @@ void RTCLossDetectionAndRecovery::onTimeout(uint32_t seq) {
last_event_ = getNow();
}
+void RTCLossDetectionAndRecovery::onPacketRecoveredFec(uint32_t seq) {
+ // if an RTX is scheduled for a packet recovered using FEC delete it
+ deleteRtx(seq);
+ recover_with_fec_.erase(seq);
+}
+
void RTCLossDetectionAndRecovery::onDataPacketReceived(
const core::ContentObject &content_object) {
last_event_ = getNow();
uint32_t seq = content_object.getName().getSuffix();
if (deleteRtx(seq)) {
- state_->onPacketRecovered(seq);
+ state_->onPacketRecoveredRtx(seq);
} else {
- if (TRANSPORT_EXPECT_FALSE(!rtx_on_)) return; // do not add if RTX is off
- TRANSPORT_LOGD("received data. add from %u to %u ",
- state_->getHighestSeqReceivedInOrder() + 1, seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "received data. add from "
+ << state_->getHighestSeqReceivedInOrder() + 1 << " to " << seq;
addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1, seq);
}
}
@@ -76,8 +133,6 @@ void RTCLossDetectionAndRecovery::onNackPacketReceived(
uint32_t seq = nack.getName().getSuffix();
- if (TRANSPORT_EXPECT_FALSE(!rtx_on_)) return; // do not add if RTX is off
-
struct nack_packet_t *nack_pkt =
(struct nack_packet_t *)nack.getPayload()->data();
uint32_t production_seq = nack_pkt->getProductionSegement();
@@ -91,8 +146,9 @@ void RTCLossDetectionAndRecovery::onNackPacketReceived(
// productionSeq = 14. 9 is lost but we can try to recover packets 12 13 and
// 14 that are not arrived yet
deleteRtx(seq);
- TRANSPORT_LOGD("received past nack. add from %u to %u ",
- state_->getHighestSeqReceivedInOrder() + 1, production_seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "received past nack. add from "
+ << state_->getHighestSeqReceivedInOrder() + 1
+ << " to " << production_seq;
addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
production_seq);
} else {
@@ -105,8 +161,9 @@ void RTCLossDetectionAndRecovery::onNackPacketReceived(
// with productionSeq = 18. this says that all the packets between 12 and 18
// may got lost and we should ask them
deleteRtx(seq);
- TRANSPORT_LOGD("received futrue nack. add from %u to %u ",
- state_->getHighestSeqReceivedInOrder() + 1, production_seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "received futrue nack. add from "
+ << state_->getHighestSeqReceivedInOrder() + 1
+ << " to " << production_seq;
addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
production_seq);
}
@@ -117,12 +174,13 @@ void RTCLossDetectionAndRecovery::onProbePacketReceived(
// we don't log the reception of a probe packet for the sentinel timer because
// probes are not taken into account into the sync window. we use them as
// future nacks to detect possible packets lost
- if (TRANSPORT_EXPECT_FALSE(!rtx_on_)) return; // do not add if RTX is off
struct nack_packet_t *probe_pkt =
(struct nack_packet_t *)probe.getPayload()->data();
uint32_t production_seq = probe_pkt->getProductionSegement();
- TRANSPORT_LOGD("received probe. add from %u to %u ",
- state_->getHighestSeqReceivedInOrder() + 1, production_seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "received probe. add from "
+ << state_->getHighestSeqReceivedInOrder() + 1 << " to " << production_seq;
+
addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
production_seq);
}
@@ -150,20 +208,41 @@ void RTCLossDetectionAndRecovery::addToRetransmissions(uint32_t start,
}
for (uint32_t seq = start; seq < stop; seq++) {
- if (!isRtx(seq) && // is not already an rtx
- // is not received or lost
- state_->isReceivedOrLost(seq) == PacketState::UNKNOWN) {
- // add rtx
- rtxState state;
- state.first_send_ = state_->getInterestSentTime(seq);
- if (state.first_send_ == 0) // this interest was never sent before
- state.first_send_ = getNow();
- state.next_send_ = computeNextSend(seq, true);
- state.rtx_count_ = 0;
- TRANSPORT_LOGD("add %u to retransmissions. next rtx is %lu ", seq,
- (state.next_send_ - getNow()));
- rtx_state_.insert(std::pair<uint32_t, rtxState>(seq, state));
- rtx_timers_.insert(std::pair<uint64_t, uint32_t>(state.next_send_, seq));
+ if (state_->isReceivedOrLost(seq) == PacketState::UNKNOWN) {
+ if (rtx_on_) {
+ if (!indexer_->isFec(seq)) {
+ // handle it with rtx
+ if (!isRtx(seq)) {
+ state_->onLossDetected(seq);
+ rtxState state;
+ state.first_send_ = state_->getInterestSentTime(seq);
+ if (state.first_send_ == 0) // this interest was never sent before
+ state.first_send_ = getNow();
+ state.next_send_ = computeNextSend(seq, true);
+ state.rtx_count_ = 0;
+ DLOG_IF(INFO, VLOG_IS_ON(4))
+ << "Add " << seq << " to retransmissions. next rtx is %lu "
+ << state.next_send_ - getNow();
+ rtx_state_.insert(std::pair<uint32_t, rtxState>(seq, state));
+ rtx_timers_.insert(
+ std::pair<uint64_t, uint32_t>(state.next_send_, seq));
+ }
+ } else {
+ // is fec, do not send it
+ auto it = recover_with_fec_.find(seq);
+ if (it == recover_with_fec_.end()) {
+ state_->onLossDetected(seq);
+ recover_with_fec_.insert(seq);
+ }
+ }
+ } else {
+ // keep track of losses but recover with FEC
+ auto it = recover_with_fec_.find(seq);
+ if (it == recover_with_fec_.end()) {
+ state_->onLossDetected(seq);
+ recover_with_fec_.insert(seq);
+ }
+ }
}
}
scheduleNextRtx();
@@ -182,13 +261,15 @@ uint64_t RTCLossDetectionAndRecovery::computeNextSend(uint32_t seq,
if (prod_rate != 0) {
double packet_size = state_->getAveragePacketSize();
- estimated_iat = (uint32_t)ceil(1000.0 / (prod_rate / packet_size));
- jitter = (uint32_t)ceil(state_->getJitter());
+ estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
+ jitter = ceil(state_->getJitter());
}
uint32_t wait = estimated_iat + jitter;
- TRANSPORT_LOGD("first rtx for %u in %u ms, rtt = %lu ait = %u jttr = %u",
- seq, wait, state_->getRTT(), estimated_iat, jitter);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "first rtx for " << seq << " in " << wait
+ << " ms, rtt = " << state_->getRTT() << " ait = " << estimated_iat
+ << " jttr = " << jitter;
return now + wait;
} else {
@@ -202,25 +283,26 @@ uint64_t RTCLossDetectionAndRecovery::computeNextSend(uint32_t seq,
}
double packet_size = state_->getAveragePacketSize();
- uint32_t estimated_iat = (uint32_t)ceil(1000.0 / (prod_rate / packet_size));
+ uint32_t estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
uint64_t rtt = state_->getRTT();
if (rtt == 0) rtt = SENTINEL_TIMER_INTERVAL;
- wait = (uint32_t)rtt;
+ wait = rtt;
if (estimated_iat > rtt) wait = estimated_iat;
- uint32_t jitter = (uint32_t)ceil(state_->getJitter());
+ uint32_t jitter = ceil(state_->getJitter());
wait += jitter;
// it may happen that the channel is congested and we have some additional
// queuing delay to take into account
- uint32_t queue = (uint32_t)ceil(state_->getQueuing());
+ uint32_t queue = ceil(state_->getQueuing());
wait += queue;
- TRANSPORT_LOGD(
- "next rtx for %u in %u ms, rtt = %lu ait = %u jttr = %u queue = %u",
- seq, wait, state_->getRTT(), estimated_iat, jitter, queue);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "next rtx for " << seq << " in " << wait
+ << " ms, rtt = " << state_->getRTT() << " ait = " << estimated_iat
+ << " jttr = " << jitter << " queue = " << queue;
return now + wait;
}
@@ -235,7 +317,7 @@ void RTCLossDetectionAndRecovery::retransmit() {
std::unordered_set<uint32_t> lost_pkt;
uint32_t sent_counter = 0;
while (it != rtx_timers_.end() && it->first <= now &&
- sent_counter < MAX_INTERESTS_IN_BATCH) {
+ sent_counter < MAX_RTX_IN_BATCH) {
uint32_t seq = it->second;
auto rtx_it =
rtx_state_.find(seq); // this should always return a valid iter
@@ -243,11 +325,11 @@ void RTCLossDetectionAndRecovery::retransmit() {
(now - rtx_it->second.first_send_) >= RTC_MAX_AGE ||
seq < state_->getLastSeqNacked()) {
// max rtx reached or packet too old or packet nacked, this packet is lost
- TRANSPORT_LOGD(
- "packet %u lost because 1) max rtx: %u 2) max age: %u 3) naked: %u",
- seq, (rtx_it->second.rtx_count_ >= RTC_MAX_RTX),
- ((now - rtx_it->second.first_send_) >= RTC_MAX_AGE),
- (seq < state_->getLastSeqNacked()));
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "packet " << seq << " lost because 1) max rtx: "
+ << (rtx_it->second.rtx_count_ >= RTC_MAX_RTX) << " 2) max age: "
+ << ((now - rtx_it->second.first_send_) >= RTC_MAX_AGE)
+ << " 3) nacked: " << (seq < state_->getLastSeqNacked());
lost_pkt.insert(seq);
it++;
} else {
@@ -259,8 +341,9 @@ void RTCLossDetectionAndRecovery::retransmit() {
it = rtx_timers_.erase(it);
rtx_timers_.insert(
std::pair<uint64_t, uint32_t>(rtx_it->second.next_send_, seq));
- TRANSPORT_LOGD("send rtx for sequence %u, next send in %lu", seq,
- (rtx_it->second.next_send_ - now));
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "send rtx for sequence " << seq << ", next send in "
+ << (rtx_it->second.next_send_ - now);
send_rtx_callback_(seq);
sent_counter++;
}
@@ -358,20 +441,21 @@ void RTCLossDetectionAndRecovery::sentinelTimer() {
if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive())) {
// this happens at the beginning (or if the producer stops for some
// reason) we need to keep sending interest 0 until we get an answer
- TRANSPORT_LOGD(
- "sentinel timer: the producer is not active, send packet 0");
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "sentinel timer: the producer is not active, send packet 0";
state_->onRetransmission(0);
send_rtx_callback_(0);
} else {
- TRANSPORT_LOGD(
- "sentinel timer: the producer is active, send the 10 oldest packets");
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "sentinel timer: the producer is active, "
+ "send the 10 oldest packets";
sent = true;
uint32_t rtx = 0;
auto it = state_->getPendingInterestsMapBegin();
auto end = state_->getPendingInterestsMapEnd();
while (it != end && rtx < MAX_RTX_WITH_SENTINEL) {
uint32_t seq = it->first;
- TRANSPORT_LOGD("sentinel timer, add %u to the rtx list", seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "sentinel timer, add " << seq << " to the rtx list";
addToRetransmissions(seq, seq + 1);
rtx++;
it++;
@@ -384,36 +468,38 @@ void RTCLossDetectionAndRecovery::sentinelTimer() {
uint32_t next_timer;
double prod_rate = state_->getProducerRate();
if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive()) || prod_rate == 0) {
- TRANSPORT_LOGD("next timer in %u", SENTINEL_TIMER_INTERVAL);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "next timer in " << SENTINEL_TIMER_INTERVAL;
next_timer = SENTINEL_TIMER_INTERVAL;
} else {
double prod_rate = state_->getProducerRate();
double packet_size = state_->getAveragePacketSize();
- uint32_t estimated_iat = (uint32_t)ceil(1000.0 / (prod_rate / packet_size));
- uint32_t jitter = (uint32_t)ceil(state_->getJitter());
+ uint32_t estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
+ uint32_t jitter = ceil(state_->getJitter());
// try to reduce the number of timers if the estimated IAT is too small
next_timer = std::max((estimated_iat + jitter) * 20, (uint32_t)1);
- TRANSPORT_LOGD("next sentinel in %u ms, rate: %f, iat: %u, jitter: %u",
- next_timer, ((prod_rate * 8.0) / 1000000.0), estimated_iat,
- jitter);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "next sentinel in " << next_timer
+ << " ms, rate: " << ((prod_rate * 8.0) / 1000000.0)
+ << ", iat: " << estimated_iat << ", jitter: " << jitter;
if (!expired) {
// discount the amout of time that is already passed
- uint32_t discount = (uint32_t)(now - last_event_);
+ uint32_t discount = now - last_event_;
if (next_timer > discount) {
next_timer = next_timer - discount;
} else {
// in this case we trigger the timer in 1 ms
next_timer = 1;
}
- TRANSPORT_LOGD("timer after discout: %u", next_timer);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "timer after discout: " << next_timer;
} else if (sent) {
// wait at least one producer stats interval + owd to check if the
// production rate is reducing.
- uint32_t min_wait = PRODUCER_STATS_INTERVAL + (uint32_t)ceil(state_->getQueuing());
+ uint32_t min_wait = PRODUCER_STATS_INTERVAL + ceil(state_->getQueuing());
next_timer = std::max(next_timer, min_wait);
- TRANSPORT_LOGD("wait for updates from prod, next timer: %u", next_timer);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "wait for updates from prod, next timer: " << next_timer;
}
}
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.h b/libtransport/src/protocols/rtc/rtc_ldr.h
index c0912303b..1b9f9afd6 100644
--- a/libtransport/src/protocols/rtc/rtc_ldr.h
+++ b/libtransport/src/protocols/rtc/rtc_ldr.h
@@ -15,15 +15,16 @@
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/name.h>
+#include <protocols/indexer.h>
#include <protocols/rtc/rtc_consts.h>
#include <protocols/rtc/rtc_state.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <functional>
#include <map>
+#include <unordered_map>
namespace transport {
@@ -43,16 +44,23 @@ class RTCLossDetectionAndRecovery
using SendRtxCallback = std::function<void(uint32_t)>;
public:
- RTCLossDetectionAndRecovery(SendRtxCallback &&callback,
+ RTCLossDetectionAndRecovery(Indexer *indexer, SendRtxCallback &&callback,
asio::io_service &io_service);
~RTCLossDetectionAndRecovery();
void setState(std::shared_ptr<RTCState> state) { state_ = state; }
+ void setFecParams(uint32_t n, uint32_t k) {
+ n_ = n;
+ k_ = k;
+ }
void turnOnRTX();
void turnOffRTX();
+ bool isRtxOn() { return rtx_on_; }
+ void onNewRound(bool in_sync);
void onTimeout(uint32_t seq);
+ void onPacketRecoveredFec(uint32_t seq);
void onDataPacketReceived(const core::ContentObject &content_object);
void onNackPacketReceived(const core::ContentObject &nack);
void onProbePacketReceived(const core::ContentObject &probe);
@@ -72,6 +80,7 @@ class RTCLossDetectionAndRecovery
bool deleteRtx(uint32_t seq);
void scheduleSentinelTimer(uint64_t expires_from_now);
void sentinelTimer();
+ uint32_t computeFecPacketsToAsk(bool in_sync);
uint64_t getNow() {
using namespace std::chrono;
@@ -90,14 +99,25 @@ class RTCLossDetectionAndRecovery
// should be sent, and the val is the interest seq number
std::multimap<uint64_t, uint32_t> rtx_timers_;
+ // lost packets that will be recovered with fec
+ std::unordered_set<uint32_t> recover_with_fec_;
+
bool rtx_on_;
+ bool fec_on_;
uint64_t next_rtx_timer_;
uint64_t last_event_;
uint64_t sentinel_timer_interval_;
+
+ // fec params
+ uint32_t n_;
+ uint32_t k_;
+
std::unique_ptr<asio::steady_timer> timer_;
std::unique_ptr<asio::steady_timer> sentinel_timer_;
std::shared_ptr<RTCState> state_;
+ Indexer *indexer_;
+
SendRtxCallback send_rtx_callback_;
};
diff --git a/libtransport/src/protocols/rtc/rtc_packet.h b/libtransport/src/protocols/rtc/rtc_packet.h
index 2f2b19fb9..7dc2f82c3 100644
--- a/libtransport/src/protocols/rtc/rtc_packet.h
+++ b/libtransport/src/protocols/rtc/rtc_packet.h
@@ -90,4 +90,4 @@ struct nack_packet_t {
} // end namespace protocol
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_frame.cc b/libtransport/src/protocols/rtc/rtc_rc_frame.cc
deleted file mode 100644
index b577b5bea..000000000
--- a/libtransport/src/protocols/rtc/rtc_rc_frame.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <protocols/rtc/rtc_consts.h>
-#include <protocols/rtc/rtc_rc_frame.h>
-
-#include <algorithm>
-
-namespace transport {
-
-namespace protocol {
-
-namespace rtc {
-
-RTCRateControlFrame::RTCRateControlFrame() : cc_detector_() {}
-
-RTCRateControlFrame::~RTCRateControlFrame() {}
-
-void RTCRateControlFrame::onNewRound(double round_len) {
- if (!rc_on_) return;
-
- CongestionState prev_congestion_state = congestion_state_;
- cc_detector_.updateStats();
- congestion_state_ = (CongestionState)cc_detector_.getState();
-
- if (congestion_state_ == CongestionState::Congested) {
- if (prev_congestion_state == CongestionState::Normal) {
- // congestion detected, notify app and init congestion win
- double prod_rate = protocol_state_->getReceivedRate();
- double rtt = (double)protocol_state_->getRTT() / MILLI_IN_A_SEC;
- double packet_size = protocol_state_->getAveragePacketSize();
-
- if (prod_rate == 0.0 || rtt == 0.0 || packet_size == 0.0) {
- // TODO do something
- return;
- }
-
- congestion_win_ = (uint32_t)ceil(prod_rate * rtt / packet_size);
- }
- uint32_t win = congestion_win_ * WIN_DECREASE_FACTOR;
- congestion_win_ = std::max(win, WIN_MIN);
- return;
- }
-}
-
-void RTCRateControlFrame::onDataPacketReceived(
- const core::ContentObject &content_object) {
- if (!rc_on_) return;
-
- uint32_t seq = content_object.getName().getSuffix();
- if (!protocol_state_->isPending(seq)) return;
-
- cc_detector_.addPacket(content_object);
-}
-
-void RTCRateControlFrame::receivedBwProbeTrain(uint64_t firts_probe_ts,
- uint64_t last_probe_ts,
- uint32_t total_probes) {
- // TODO
- return;
-}
-
-} // end namespace rtc
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_frame.h b/libtransport/src/protocols/rtc/rtc_rc_frame.h
deleted file mode 100644
index 25d5ddbb6..000000000
--- a/libtransport/src/protocols/rtc/rtc_rc_frame.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2017-2021 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-#include <protocols/rtc/congestion_detection.h>
-#include <protocols/rtc/rtc_rc.h>
-
-namespace transport {
-
-namespace protocol {
-
-namespace rtc {
-
-class RTCRateControlFrame : public RTCRateControl {
- public:
- RTCRateControlFrame();
-
- ~RTCRateControlFrame();
-
- void onNewRound(double round_len);
- void onDataPacketReceived(const core::ContentObject &content_object);
-
- void receivedBwProbeTrain(uint64_t firts_probe_ts, uint64_t last_probe_ts,
- uint32_t total_probes);
-
- private:
- CongestionDetection cc_detector_;
-};
-
-} // end namespace rtc
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_queue.cc b/libtransport/src/protocols/rtc/rtc_rc_queue.cc
index 3c7318dae..a1c89e329 100644
--- a/libtransport/src/protocols/rtc/rtc_rc_queue.cc
+++ b/libtransport/src/protocols/rtc/rtc_rc_queue.cc
@@ -67,11 +67,11 @@ void RTCRateControlQueue::onNewRound(double round_len) {
if (prev_congestion_state == CongestionState::Normal) {
// init the congetion window using the received rate
congestion_win_ = (uint32_t)ceil(received_rate * rtt / packet_size);
- rounds_since_last_drop_ = (uint32_t)ROUNDS_BEFORE_TAKE_ACTION + 1;
+ rounds_since_last_drop_ = ROUNDS_BEFORE_TAKE_ACTION + 1;
}
if (rounds_since_last_drop_ >= ROUNDS_BEFORE_TAKE_ACTION) {
- uint32_t win = congestion_win_ * (uint32_t)WIN_DECREASE_FACTOR;
+ uint32_t win = congestion_win_ * WIN_DECREASE_FACTOR;
congestion_win_ = std::max(win, WIN_MIN);
rounds_since_last_drop_ = 0;
return;
@@ -88,7 +88,7 @@ void RTCRateControlQueue::onNewRound(double round_len) {
rounds_without_congestion_++;
if (rounds_without_congestion_ < ROUNDS_BEFORE_TAKE_ACTION) return;
- congestion_win_ = congestion_win_ * (uint32_t)WIN_INCREASE_FACTOR;
+ congestion_win_ = congestion_win_ * WIN_INCREASE_FACTOR;
congestion_win_ = std::min(congestion_win_, INITIAL_WIN_MAX);
}
}
diff --git a/libtransport/src/protocols/rtc/rtc_reassembly.h b/libtransport/src/protocols/rtc/rtc_reassembly.h
new file mode 100644
index 000000000..15722a6d5
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_reassembly.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <glog/logging.h>
+#include <protocols/datagram_reassembly.h>
+#include <protocols/rtc/rtc_consts.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RtcReassembly : public DatagramReassembly {
+ public:
+ RtcReassembly(implementation::ConsumerSocket *icn_socket,
+ TransportProtocol *transport_protocol)
+ : DatagramReassembly(icn_socket, transport_protocol) {}
+
+ void reassemble(core::ContentObject &content_object) override {
+ auto read_buffer = content_object.getPayload();
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Size of payload: " << read_buffer->length();
+ read_buffer->trimStart(transport_protocol_->transportHeaderLength());
+ Reassembly::read_buffer_ = std::move(read_buffer);
+ Reassembly::notifyApplication();
+ }
+};
+
+} // namespace rtc
+} // namespace protocol
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_state.cc b/libtransport/src/protocols/rtc/rtc_state.cc
index 9c965bfed..c99205a26 100644
--- a/libtransport/src/protocols/rtc/rtc_state.cc
+++ b/libtransport/src/protocols/rtc/rtc_state.cc
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <protocols/rtc/rtc_consts.h>
#include <protocols/rtc/rtc_state.h>
@@ -22,11 +23,13 @@ namespace protocol {
namespace rtc {
-RTCState::RTCState(ProbeHandler::SendProbeCallback &&rtt_probes_callback,
+RTCState::RTCState(Indexer *indexer,
+ ProbeHandler::SendProbeCallback &&rtt_probes_callback,
DiscoveredRttCallback &&discovered_rtt_callback,
asio::io_service &io_service)
- : rtt_probes_(std::make_shared<ProbeHandler>(
- std::move(rtt_probes_callback), io_service)),
+ : indexer_(indexer),
+ rtt_probes_(std::make_shared<ProbeHandler>(std::move(rtt_probes_callback),
+ io_service)),
discovered_rtt_callback_(std::move(discovered_rtt_callback)) {
init_rtt_timer_ = std::make_unique<asio::steady_timer>(io_service);
initParams();
@@ -45,14 +48,22 @@ void RTCState::initParams() {
// loss counters
packets_lost_ = 0;
+ definitely_lost_pkt_ = 0;
losses_recovered_ = 0;
first_seq_in_round_ = 0;
highest_seq_received_ = 0;
highest_seq_received_in_order_ = 0;
last_seq_nacked_ = 0;
loss_rate_ = 0.0;
+ avg_loss_rate_ = 0.0;
+ max_loss_rate_ = 0.0;
+ last_round_loss_rate_ = 0.0;
residual_loss_rate_ = 0.0;
+ // fec counters
+ pending_fec_pkt_ = 0;
+ received_fec_pkt_ = 0;
+
// bw counters
received_bytes_ = 0;
avg_packet_size_ = INIT_PACKET_SIZE;
@@ -90,8 +101,14 @@ void RTCState::initParams() {
// pending interests
pending_interests_.clear();
+ // skipped interest
+ last_interest_sent_ = 0;
+ skipped_interests_.clear();
+
// init rtt
- first_interest_sent_ = ~0;
+ first_interest_sent_time_ = ~0;
+ first_interest_sent_seq_ = 0;
+
init_rtt_ = false;
rtt_probes_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
rtt_probes_->sendProbes();
@@ -106,18 +123,51 @@ void RTCState::onSendNewInterest(const core::Name *interest_name) {
uint32_t seq = interest_name->getSuffix();
pending_interests_.insert(std::pair<uint32_t, uint64_t>(seq, now));
- if(sent_interests_ == 0) first_interest_sent_ = now;
+ if (sent_interests_ == 0) {
+ first_interest_sent_time_ = now;
+ first_interest_sent_seq_ = seq;
+ }
+
+ if (indexer_->isFec(seq)) {
+ pending_fec_pkt_++;
+ }
+
+ if (last_interest_sent_ == 0 && seq != 0) {
+ last_interest_sent_ = seq; // init last interest sent
+ }
+
+ // TODO what happen in case of jumps?
+ // look for skipped interests
+ skipped_interests_.erase(seq); // remove seq if it is there
+ for (uint32_t i = last_interest_sent_ + 1; i < seq; i++) {
+ if (indexer_->isFec(i)) {
+ skipped_interests_.insert(i);
+ }
+ }
+
+ last_interest_sent_ = seq;
sent_interests_++;
sent_interests_last_round_++;
}
-void RTCState::onTimeout(uint32_t seq) {
+void RTCState::onTimeout(uint32_t seq, bool lost) {
auto it = pending_interests_.find(seq);
if (it != pending_interests_.end()) {
pending_interests_.erase(it);
}
received_timeouts_++;
+
+ if (lost) onPacketLost(seq);
+}
+
+void RTCState::onLossDetected(uint32_t seq) {
+ if (!indexer_->isFec(seq)) {
+ packets_lost_++;
+ } else if (skipped_interests_.find(seq) == skipped_interests_.end() &&
+ seq >= first_interest_sent_seq_) {
+ packets_lost_++;
+ }
}
void RTCState::onRetransmission(uint32_t seq) {
@@ -128,7 +178,9 @@ void RTCState::onRetransmission(uint32_t seq) {
auto it = pending_interests_.find(seq);
if (it != pending_interests_.end()) {
pending_interests_.erase(it);
+#if 0
packets_lost_++;
+#endif
}
sent_rtx_++;
sent_rtx_last_round_++;
@@ -165,6 +217,16 @@ void RTCState::onDataPacketReceived(const core::ContentObject &content_object,
received_packets_last_round_++;
}
+void RTCState::onFecPacketReceived(const core::ContentObject &content_object) {
+ uint32_t seq = content_object.getName().getSuffix();
+ updateReceivedBytes(content_object);
+ addRecvOrLost(seq, PacketState::RECEIVED);
+ received_fec_pkt_++;
+ // the producer is responding
+ // it is generating valid data packets so we consider it active
+ producer_is_active_ = true;
+}
+
void RTCState::onNackPacketReceived(const core::ContentObject &nack,
bool compute_stats) {
uint32_t seq = nack.getName().getSuffix();
@@ -197,12 +259,14 @@ void RTCState::onNackPacketReceived(const core::ContentObject &nack,
// old nack, seq is lost
// update last nacked
if (last_seq_nacked_ < seq) last_seq_nacked_ = seq;
- TRANSPORT_LOGD("lost packet %u beacuse of a past nack", seq);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "lost packet " << seq << " beacuse of a past nack";
onPacketLost(seq);
} else if (seq > production_seq) {
// future nack
// remove the nack from the pending interest map
// (the packet is not received/lost yet)
+ if (indexer_->isFec(seq)) pending_fec_pkt_--;
pending_interests_.erase(seq);
} else {
// this should be a quite rear event. simply remove the
@@ -221,17 +285,28 @@ void RTCState::onNackPacketReceived(const core::ContentObject &nack,
}
void RTCState::onPacketLost(uint32_t seq) {
- TRANSPORT_LOGD("packet %u is lost", seq);
+#if 0
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "packet " << seq << " is lost";
auto it = pending_interests_.find(seq);
if (it != pending_interests_.end()) {
// this packet was never retransmitted so it does
// not appear in the loss count
packets_lost_++;
}
+#endif
+ if (!indexer_->isFec(seq)) {
+ definitely_lost_pkt_++;
+ DLOG_IF(INFO, VLOG_IS_ON(4)) << "packet " << seq << " is lost";
+ }
addRecvOrLost(seq, PacketState::LOST);
}
-void RTCState::onPacketRecovered(uint32_t seq) {
+void RTCState::onPacketRecoveredRtx(uint32_t seq) {
+ losses_recovered_++;
+ addRecvOrLost(seq, PacketState::RECEIVED);
+}
+
+void RTCState::onPacketRecoveredFec(uint32_t seq) {
losses_recovered_++;
addRecvOrLost(seq, PacketState::RECEIVED);
}
@@ -258,7 +333,6 @@ bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
uint32_t production_seq = probe_pkt->getProductionSegement();
uint32_t production_rate = probe_pkt->getProductionRate();
-
if (path_it == path_table_.end()) {
// found a new path
std::shared_ptr<RTCDataPath> newPath =
@@ -298,13 +372,14 @@ bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
// wait forever
received_probes_++;
- if(!init_rtt_ && received_probes_ <= INIT_RTT_PROBES){
- if(received_probes_ == 1){
- // we got the first probe, wait at most INIT_RTT_PROBE_WAIT sec for the others
+ if (!init_rtt_ && received_probes_ <= INIT_RTT_PROBES) {
+ if (received_probes_ == 1) {
+ // we got the first probe, wait at most INIT_RTT_PROBE_WAIT sec for the
+ // others
main_path_ = path;
setInitRttTimer(INIT_RTT_PROBE_WAIT);
}
- if(received_probes_ == INIT_RTT_PROBES) {
+ if (received_probes_ == INIT_RTT_PROBES) {
// we are done
init_rtt_timer_->cancel();
checkInitRttTimer();
@@ -314,7 +389,7 @@ bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
received_packets_last_round_++;
// ignore probes sent before the first interest
- if((now - rtt) <= first_interest_sent_) return false;
+ if ((now - rtt) <= first_interest_sent_time_) return false;
return true;
}
@@ -327,11 +402,11 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
double bytes_per_sec =
((double)received_bytes_ * (MILLI_IN_A_SEC / round_len));
- if(received_rate_ == 0)
+ if (received_rate_ == 0)
received_rate_ = bytes_per_sec;
else
received_rate_ = (received_rate_ * MOVING_AVG_ALPHA) +
- ((1 - MOVING_AVG_ALPHA) * bytes_per_sec);
+ ((1 - MOVING_AVG_ALPHA) * bytes_per_sec);
// search for an active path. There should be only one active path (meaning a
// path that leads to the producer socket -no cache- and from which we are
@@ -354,7 +429,8 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
}
}
- if (in_sync) updateLossRate();
+ // if (in_sync) updateLossRate();
+ updateLossRate();
// handle nacks
if (!nack_on_last_round_ && received_bytes_ > 0) {
@@ -385,6 +461,7 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
// reset counters
received_bytes_ = 0;
packets_lost_ = 0;
+ definitely_lost_pkt_ = 0;
losses_recovered_ = 0;
first_seq_in_round_ = highest_seq_received_;
@@ -397,6 +474,8 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
sent_interests_last_round_ = 0;
sent_rtx_last_round_ = 0;
+ received_fec_pkt_ = 0;
+
rounds_++;
}
@@ -465,6 +544,7 @@ void RTCState::updatePathStats(const core::ContentObject &content_object,
}
void RTCState::updateLossRate() {
+ last_round_loss_rate_ = loss_rate_;
loss_rate_ = 0.0;
residual_loss_rate_ = 0.0;
@@ -475,9 +555,29 @@ void RTCState::updateLossRate() {
// division by 0
if (number_theorically_received_packets_ == 0) return;
+ // XXX this may be quite inefficient if the rate is high
+ // maybe is better to iterate over the set?
+ for (uint32_t i = first_seq_in_round_; i < highest_seq_received_; i++) {
+ auto it = skipped_interests_.find(i);
+ if (it != skipped_interests_.end()) {
+ if (number_theorically_received_packets_ > 0)
+ number_theorically_received_packets_--;
+ skipped_interests_.erase(it);
+ }
+ }
+
loss_rate_ = (double)((double)(packets_lost_) /
(double)number_theorically_received_packets_);
+ if (rounds_ % 15 == 0) max_loss_rate_ = 0; // reset every 3 sec
+ if (loss_rate_ > max_loss_rate_) max_loss_rate_ = loss_rate_;
+
+ if (avg_loss_rate_ == 0)
+ avg_loss_rate_ = loss_rate_;
+ else
+ avg_loss_rate_ =
+ avg_loss_rate_ * MOVING_AVG_ALPHA + loss_rate_ * (1 - MOVING_AVG_ALPHA);
+
residual_loss_rate_ = (double)((double)(packets_lost_ - losses_recovered_) /
(double)number_theorically_received_packets_);
@@ -485,6 +585,10 @@ void RTCState::updateLossRate() {
}
void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
+ if (indexer_->isFec(seq)) {
+ pending_fec_pkt_--;
+ }
+
pending_interests_.erase(seq);
if (received_or_lost_packets_.size() >= MAX_CACHED_PACKETS) {
received_or_lost_packets_.erase(received_or_lost_packets_.begin());
@@ -507,10 +611,12 @@ void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
// 1) there is a gap in the sequence so we do not update largest_in_seq_
// 2) all the packets from largest_in_seq_ to seq are in
// received_or_lost_packets_ an we upate largest_in_seq_
+ // or are FEC packets
for (uint32_t i = highest_seq_received_in_order_ + 1; i <= seq; i++) {
if (received_or_lost_packets_.find(i) ==
- received_or_lost_packets_.end()) {
+ received_or_lost_packets_.end() &&
+ !indexer_->isFec(i)) {
break;
}
// this packet is in order so we can update the
@@ -520,17 +626,17 @@ void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
}
}
-void RTCState::setInitRttTimer(uint32_t wait){
+void RTCState::setInitRttTimer(uint32_t wait) {
init_rtt_timer_->cancel();
init_rtt_timer_->expires_from_now(std::chrono::milliseconds(wait));
init_rtt_timer_->async_wait([this](std::error_code ec) {
- if(ec) return;
+ if (ec) return;
checkInitRttTimer();
});
}
void RTCState::checkInitRttTimer() {
- if(received_probes_ < INIT_RTT_MIN_PROBES_TO_RECV){
+ if (received_probes_ < INIT_RTT_MIN_PROBES_TO_RECV) {
// we didn't received enough probes, restart
received_probes_ = 0;
rtt_probes_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
@@ -547,7 +653,7 @@ void RTCState::checkInitRttTimer() {
double prod_rate = getProducerRate();
double rtt = (double)getRTT() / MILLI_IN_A_SEC;
double packet_size = getAveragePacketSize();
- uint32_t pkt_in_rtt_ = (uint32_t)std::floor(((prod_rate / packet_size) * rtt) * 0.8);
+ uint32_t pkt_in_rtt_ = std::floor(((prod_rate / packet_size) * rtt) * 0.8);
last_seq_nacked_ = last_production_seq_ + pkt_in_rtt_;
discovered_rtt_callback_();
diff --git a/libtransport/src/protocols/rtc/rtc_state.h b/libtransport/src/protocols/rtc/rtc_state.h
index e4fefaffe..729ba7a1b 100644
--- a/libtransport/src/protocols/rtc/rtc_state.h
+++ b/libtransport/src/protocols/rtc/rtc_state.h
@@ -15,13 +15,13 @@
#pragma once
#include <hicn/transport/config.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/name.h>
+#include <protocols/indexer.h>
#include <protocols/rtc/probe_handler.h>
#include <protocols/rtc/rtc_data_path.h>
-#include <asio.hpp>
-#include <asio/steady_timer.hpp>
#include <map>
#include <set>
@@ -36,8 +36,10 @@ enum class PacketState : uint8_t { RECEIVED, LOST, UNKNOWN };
class RTCState : std::enable_shared_from_this<RTCState> {
public:
using DiscoveredRttCallback = std::function<void()>;
+
public:
- RTCState(ProbeHandler::SendProbeCallback &&rtt_probes_callback,
+ RTCState(Indexer *indexer,
+ ProbeHandler::SendProbeCallback &&rtt_probes_callback,
DiscoveredRttCallback &&discovered_rtt_callback,
asio::io_service &io_service);
@@ -45,14 +47,17 @@ class RTCState : std::enable_shared_from_this<RTCState> {
// packet events
void onSendNewInterest(const core::Name *interest_name);
- void onTimeout(uint32_t seq);
+ void onTimeout(uint32_t seq, bool lost);
+ void onLossDetected(uint32_t seq);
void onRetransmission(uint32_t seq);
void onDataPacketReceived(const core::ContentObject &content_object,
bool compute_stats);
+ void onFecPacketReceived(const core::ContentObject &content_object);
void onNackPacketReceived(const core::ContentObject &nack,
bool compute_stats);
void onPacketLost(uint32_t seq);
- void onPacketRecovered(uint32_t seq);
+ void onPacketRecoveredRtx(uint32_t seq);
+ void onPacketRecoveredFec(uint32_t seq);
bool onProbePacketReceived(const core::ContentObject &probe);
// protocol state
@@ -65,9 +70,7 @@ class RTCState : std::enable_shared_from_this<RTCState> {
}
// delay metrics
- bool isRttDiscovered() const {
- return init_rtt_;
- }
+ bool isRttDiscovered() const { return init_rtt_; }
uint64_t getRTT() const {
if (mainPathIsValid()) return main_path_->getMinRtt();
@@ -97,13 +100,16 @@ class RTCState : std::enable_shared_from_this<RTCState> {
if (it != pending_interests_.end()) return it->second;
return 0;
}
+
bool isPending(uint32_t seq) {
if (pending_interests_.find(seq) != pending_interests_.end()) return true;
return false;
}
+
uint32_t getPendingInterestNumber() const {
- return (uint32_t)pending_interests_.size();
+ return pending_interests_.size();
}
+
PacketState isReceivedOrLost(uint32_t seq) {
auto it = received_or_lost_packets_.find(seq);
if (it != received_or_lost_packets_.end()) return it->second;
@@ -112,12 +118,25 @@ class RTCState : std::enable_shared_from_this<RTCState> {
// loss rate
double getLossRate() const { return loss_rate_; }
+ double getAvgLossRate() const { return avg_loss_rate_; }
+ double getMaxLossRate() const { return max_loss_rate_; }
+ double getLastRoundLossRate() const { return last_round_loss_rate_; }
double getResidualLossRate() const { return residual_loss_rate_; }
+
+ uint32_t getLostData() const { return packets_lost_; };
+ uint32_t getRecoveredLosses() const { return losses_recovered_; }
+
+ uint32_t getDefinitelyLostPackets() const { return definitely_lost_pkt_; }
+
+ uint32_t getHighestSeqReceived() const { return highest_seq_received_; }
+
uint32_t getHighestSeqReceivedInOrder() const {
return highest_seq_received_in_order_;
}
- uint32_t getLostData() const { return packets_lost_; };
- uint32_t getRecoveredLosses() const { return losses_recovered_; }
+
+ // fec packets
+ uint32_t getReceivedFecPackets() const { return received_fec_pkt_; }
+ uint32_t getPendingFecPackets() const { return pending_fec_pkt_; }
// generic stats
uint32_t getReceivedBytesInRound() const { return received_bytes_; }
@@ -183,11 +202,15 @@ class RTCState : std::enable_shared_from_this<RTCState> {
// loss counters
int32_t packets_lost_;
int32_t losses_recovered_;
+ uint32_t definitely_lost_pkt_;
uint32_t first_seq_in_round_;
uint32_t highest_seq_received_;
uint32_t highest_seq_received_in_order_;
uint32_t last_seq_nacked_; // segment for which we got an oldNack
double loss_rate_;
+ double avg_loss_rate_;
+ double max_loss_rate_;
+ double last_round_loss_rate_;
double residual_loss_rate_;
// bw counters
@@ -211,18 +234,24 @@ class RTCState : std::enable_shared_from_this<RTCState> {
uint32_t sent_interests_last_round_;
uint32_t sent_rtx_last_round_;
+ // fec counter
+ uint32_t received_fec_pkt_;
+ uint32_t pending_fec_pkt_;
+
// round conunters
uint32_t rounds_;
uint32_t rounds_without_nacks_;
uint32_t rounds_without_packets_;
// init rtt
- uint64_t first_interest_sent_;
+ uint64_t first_interest_sent_time_;
+ uint32_t first_interest_sent_seq_;
// producer state
bool
producer_is_active_; // the prodcuer is active if we receive some packets
- uint32_t last_production_seq_; // last production seq received by the producer
+ uint32_t
+ last_production_seq_; // last production seq received by the producer
uint64_t last_prod_update_; // timestamp of the last packets used to update
// stats from the producer
@@ -237,6 +266,13 @@ class RTCState : std::enable_shared_from_this<RTCState> {
// pending interests
std::map<uint32_t, uint64_t> pending_interests_;
+ // indexer
+ Indexer *indexer_;
+
+ // skipped interests
+ uint32_t last_interest_sent_;
+ std::unordered_set<uint32_t> skipped_interests_;
+
// probes
std::shared_ptr<ProbeHandler> rtt_probes_;
bool init_rtt_;
diff --git a/libtransport/src/protocols/rtc/trendline_estimator.cc b/libtransport/src/protocols/rtc/trendline_estimator.cc
deleted file mode 100644
index 7a0803857..000000000
--- a/libtransport/src/protocols/rtc/trendline_estimator.cc
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-// FROM
-// https://source.chromium.org/chromium/chromium/src/+/master:third_party/webrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc
-
-#include "trendline_estimator.h"
-
-#include <math.h>
-
-#include <algorithm>
-#include <string>
-
-namespace transport {
-
-namespace protocol {
-
-namespace rtc {
-
-// Parameters for linear least squares fit of regression line to noisy data.
-constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
-constexpr double kDefaultTrendlineThresholdGain = 4.0;
-// const char kBweWindowSizeInPacketsExperiment[] =
-// "WebRTC-BweWindowSizeInPackets";
-
-/*size_t ReadTrendlineFilterWindowSize(
- const WebRtcKeyValueConfig* key_value_config) {
- std::string experiment_string =
- key_value_config->Lookup(kBweWindowSizeInPacketsExperiment);
- size_t window_size;
- int parsed_values =
- sscanf(experiment_string.c_str(), "Enabled-%zu", &window_size);
- if (parsed_values == 1) {
- if (window_size > 1)
- return window_size;
- RTC_LOG(WARNING) << "Window size must be greater than 1.";
- }
- RTC_LOG(LS_WARNING) << "Failed to parse parameters for BweWindowSizeInPackets"
- " experiment from field trial string. Using default.";
- return TrendlineEstimatorSettings::kDefaultTrendlineWindowSize;
-}
-*/
-
-OptionalDouble LinearFitSlope(
- const std::deque<TrendlineEstimator::PacketTiming>& packets) {
- // RTC_DCHECK(packets.size() >= 2);
- // Compute the "center of mass".
- double sum_x = 0;
- double sum_y = 0;
- for (const auto& packet : packets) {
- sum_x += packet.arrival_time_ms;
- sum_y += packet.smoothed_delay_ms;
- }
- double x_avg = sum_x / packets.size();
- double y_avg = sum_y / packets.size();
- // Compute the slope k = \sum (x_i-x_avg)(y_i-y_avg) / \sum (x_i-x_avg)^2
- double numerator = 0;
- double denominator = 0;
- for (const auto& packet : packets) {
- double x = packet.arrival_time_ms;
- double y = packet.smoothed_delay_ms;
- numerator += (x - x_avg) * (y - y_avg);
- denominator += (x - x_avg) * (x - x_avg);
- }
- if (denominator == 0) return OptionalDouble();
- return OptionalDouble(numerator / denominator);
-}
-
-OptionalDouble ComputeSlopeCap(
- const std::deque<TrendlineEstimator::PacketTiming>& packets,
- const TrendlineEstimatorSettings& settings) {
- /*RTC_DCHECK(1 <= settings.beginning_packets &&
- settings.beginning_packets < packets.size());
- RTC_DCHECK(1 <= settings.end_packets &&
- settings.end_packets < packets.size());
- RTC_DCHECK(settings.beginning_packets + settings.end_packets <=
- packets.size());*/
- TrendlineEstimator::PacketTiming early = packets[0];
- for (size_t i = 1; i < settings.beginning_packets; ++i) {
- if (packets[i].raw_delay_ms < early.raw_delay_ms) early = packets[i];
- }
- size_t late_start = packets.size() - settings.end_packets;
- TrendlineEstimator::PacketTiming late = packets[late_start];
- for (size_t i = late_start + 1; i < packets.size(); ++i) {
- if (packets[i].raw_delay_ms < late.raw_delay_ms) late = packets[i];
- }
- if (late.arrival_time_ms - early.arrival_time_ms < 1) {
- return OptionalDouble();
- }
- return OptionalDouble((late.raw_delay_ms - early.raw_delay_ms) /
- (late.arrival_time_ms - early.arrival_time_ms) +
- settings.cap_uncertainty);
-}
-
-constexpr double kMaxAdaptOffsetMs = 15.0;
-constexpr double kOverUsingTimeThreshold = 10;
-constexpr int kMinNumDeltas = 60;
-constexpr int kDeltaCounterMax = 1000;
-
-//} // namespace
-
-constexpr char TrendlineEstimatorSettings::kKey[];
-
-TrendlineEstimatorSettings::TrendlineEstimatorSettings(
- /*const WebRtcKeyValueConfig* key_value_config*/) {
- /*if (absl::StartsWith(
- key_value_config->Lookup(kBweWindowSizeInPacketsExperiment),
- "Enabled")) {
- window_size = ReadTrendlineFilterWindowSize(key_value_config);
- }
- Parser()->Parse(key_value_config->Lookup(TrendlineEstimatorSettings::kKey));*/
- window_size = kDefaultTrendlineWindowSize;
- enable_cap = false;
- beginning_packets = end_packets = 0;
- cap_uncertainty = 0.0;
-
- /*if (window_size < 10 || 200 < window_size) {
- RTC_LOG(LS_WARNING) << "Window size must be between 10 and 200 packets";
- window_size = kDefaultTrendlineWindowSize;
- }
- if (enable_cap) {
- if (beginning_packets < 1 || end_packets < 1 ||
- beginning_packets > window_size || end_packets > window_size) {
- RTC_LOG(LS_WARNING) << "Size of beginning and end must be between 1 and "
- << window_size;
- enable_cap = false;
- beginning_packets = end_packets = 0;
- cap_uncertainty = 0.0;
- }
- if (beginning_packets + end_packets > window_size) {
- RTC_LOG(LS_WARNING)
- << "Size of beginning plus end can't exceed the window size";
- enable_cap = false;
- beginning_packets = end_packets = 0;
- cap_uncertainty = 0.0;
- }
- if (cap_uncertainty < 0.0 || 0.025 < cap_uncertainty) {
- RTC_LOG(LS_WARNING) << "Cap uncertainty must be between 0 and 0.025";
- cap_uncertainty = 0.0;
- }
- }*/
-}
-
-/*std::unique_ptr<StructParametersParser> TrendlineEstimatorSettings::Parser() {
- return StructParametersParser::Create("sort", &enable_sort, //
- "cap", &enable_cap, //
- "beginning_packets",
- &beginning_packets, //
- "end_packets", &end_packets, //
- "cap_uncertainty", &cap_uncertainty, //
- "window_size", &window_size);
-}*/
-
-TrendlineEstimator::TrendlineEstimator(
- /*const WebRtcKeyValueConfig* key_value_config,
- NetworkStatePredictor* network_state_predictor*/)
- : settings_(),
- smoothing_coef_(kDefaultTrendlineSmoothingCoeff),
- threshold_gain_(kDefaultTrendlineThresholdGain),
- num_of_deltas_(0),
- first_arrival_time_ms_(-1),
- accumulated_delay_(0),
- smoothed_delay_(0),
- delay_hist_(),
- k_up_(0.0087),
- k_down_(0.039),
- overusing_time_threshold_(kOverUsingTimeThreshold),
- threshold_(12.5),
- prev_modified_trend_(NAN),
- last_update_ms_(-1),
- prev_trend_(0.0),
- time_over_using_(-1),
- overuse_counter_(0),
- hypothesis_(BandwidthUsage::kBwNormal){
- // hypothesis_predicted_(BandwidthUsage::kBwNormal){//},
- // network_state_predictor_(network_state_predictor) {
- /* RTC_LOG(LS_INFO)
- << "Using Trendline filter for delay change estimation with settings "
- << settings_.Parser()->Encode() << " and "
- // << (network_state_predictor_ ? "injected" : "no")
- << " network state predictor";*/
-}
-
-TrendlineEstimator::~TrendlineEstimator() {}
-
-void TrendlineEstimator::UpdateTrendline(double recv_delta_ms,
- double send_delta_ms,
- int64_t send_time_ms,
- int64_t arrival_time_ms,
- size_t packet_size) {
- const double delta_ms = recv_delta_ms - send_delta_ms;
- ++num_of_deltas_;
- num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax);
- if (first_arrival_time_ms_ == -1) first_arrival_time_ms_ = arrival_time_ms;
-
- // Exponential backoff filter.
- accumulated_delay_ += delta_ms;
- // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
- // accumulated_delay_);
- smoothed_delay_ = smoothing_coef_ * smoothed_delay_ +
- (1 - smoothing_coef_) * accumulated_delay_;
- // BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms,
- // smoothed_delay_);
-
- // Maintain packet window
- delay_hist_.emplace_back(
- static_cast<double>(arrival_time_ms - first_arrival_time_ms_),
- smoothed_delay_, accumulated_delay_);
- if (settings_.enable_sort) {
- for (size_t i = delay_hist_.size() - 1;
- i > 0 &&
- delay_hist_[i].arrival_time_ms < delay_hist_[i - 1].arrival_time_ms;
- --i) {
- std::swap(delay_hist_[i], delay_hist_[i - 1]);
- }
- }
- if (delay_hist_.size() > settings_.window_size) delay_hist_.pop_front();
-
- // Simple linear regression.
- double trend = prev_trend_;
- if (delay_hist_.size() == settings_.window_size) {
- // Update trend_ if it is possible to fit a line to the data. The delay
- // trend can be seen as an estimate of (send_rate - capacity)/capacity.
- // 0 < trend < 1 -> the delay increases, queues are filling up
- // trend == 0 -> the delay does not change
- // trend < 0 -> the delay decreases, queues are being emptied
- OptionalDouble trendO = LinearFitSlope(delay_hist_);
- if (trendO.has_value()) trend = trendO.value();
- if (settings_.enable_cap) {
- OptionalDouble cap = ComputeSlopeCap(delay_hist_, settings_);
- // We only use the cap to filter out overuse detections, not
- // to detect additional underuses.
- if (trend >= 0 && cap.has_value() && trend > cap.value()) {
- trend = cap.value();
- }
- }
- }
- // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend);
-
- Detect(trend, send_delta_ms, arrival_time_ms);
-}
-
-void TrendlineEstimator::Update(double recv_delta_ms, double send_delta_ms,
- int64_t send_time_ms, int64_t arrival_time_ms,
- size_t packet_size, bool calculated_deltas) {
- if (calculated_deltas) {
- UpdateTrendline(recv_delta_ms, send_delta_ms, send_time_ms, arrival_time_ms,
- packet_size);
- }
- /*if (network_state_predictor_) {
- hypothesis_predicted_ = network_state_predictor_->Update(
- send_time_ms, arrival_time_ms, hypothesis_);
- }*/
-}
-
-BandwidthUsage TrendlineEstimator::State() const {
- return /*network_state_predictor_ ? hypothesis_predicted_ :*/ hypothesis_;
-}
-
-void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) {
- /*if (num_of_deltas_ < 2) {
- hypothesis_ = BandwidthUsage::kBwNormal;
- return;
- }*/
-
- const double modified_trend =
- std::min(num_of_deltas_, kMinNumDeltas) * trend * threshold_gain_;
- prev_modified_trend_ = modified_trend;
- // BWE_TEST_LOGGING_PLOT(1, "T", now_ms, modified_trend);
- // BWE_TEST_LOGGING_PLOT(1, "threshold", now_ms, threshold_);
- if (modified_trend > threshold_) {
- if (time_over_using_ == -1) {
- // Initialize the timer. Assume that we've been
- // over-using half of the time since the previous
- // sample.
- time_over_using_ = ts_delta / 2;
- } else {
- // Increment timer
- time_over_using_ += ts_delta;
- }
- overuse_counter_++;
- if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) {
- if (trend >= prev_trend_) {
- time_over_using_ = 0;
- overuse_counter_ = 0;
- hypothesis_ = BandwidthUsage::kBwOverusing;
- }
- }
- } else if (modified_trend < -threshold_) {
- time_over_using_ = -1;
- overuse_counter_ = 0;
- hypothesis_ = BandwidthUsage::kBwUnderusing;
- } else {
- time_over_using_ = -1;
- overuse_counter_ = 0;
- hypothesis_ = BandwidthUsage::kBwNormal;
- }
- prev_trend_ = trend;
- UpdateThreshold(modified_trend, now_ms);
-}
-
-void TrendlineEstimator::UpdateThreshold(double modified_trend,
- int64_t now_ms) {
- if (last_update_ms_ == -1) last_update_ms_ = now_ms;
-
- if (fabs(modified_trend) > threshold_ + kMaxAdaptOffsetMs) {
- // Avoid adapting the threshold to big latency spikes, caused e.g.,
- // by a sudden capacity drop.
- last_update_ms_ = now_ms;
- return;
- }
-
- const double k = fabs(modified_trend) < threshold_ ? k_down_ : k_up_;
- const int64_t kMaxTimeDeltaMs = 100;
- int64_t time_delta_ms = std::min(now_ms - last_update_ms_, kMaxTimeDeltaMs);
- threshold_ += k * (fabs(modified_trend) - threshold_) * time_delta_ms;
- if (threshold_ < 6.f) threshold_ = 6.f;
- if (threshold_ > 600.f) threshold_ = 600.f;
- // threshold_ = rtc::SafeClamp(threshold_, 6.f, 600.f);
- last_update_ms_ = now_ms;
-}
-
-} // namespace rtc
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/trendline_estimator.h b/libtransport/src/protocols/rtc/trendline_estimator.h
deleted file mode 100644
index 372acbc67..000000000
--- a/libtransport/src/protocols/rtc/trendline_estimator.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-// FROM
-// https://source.chromium.org/chromium/chromium/src/+/master:third_party/webrtc/modules/congestion_controller/goog_cc/trendline_estimator.h
-
-#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_
-#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <deque>
-#include <memory>
-#include <utility>
-
-namespace transport {
-
-namespace protocol {
-
-namespace rtc {
-
-class OptionalDouble {
- public:
- OptionalDouble() : val(0), has_val(false){};
- OptionalDouble(double val) : val(val), has_val(true){};
-
- double value() { return val; }
- bool has_value() { return has_val; }
-
- private:
- double val;
- bool has_val;
-};
-
-enum class BandwidthUsage {
- kBwNormal = 0,
- kBwUnderusing = 1,
- kBwOverusing = 2,
- kLast
-};
-
-struct TrendlineEstimatorSettings {
- static constexpr char kKey[] = "WebRTC-Bwe-TrendlineEstimatorSettings";
- static constexpr unsigned kDefaultTrendlineWindowSize = 20;
-
- // TrendlineEstimatorSettings() = delete;
- TrendlineEstimatorSettings(
- /*const WebRtcKeyValueConfig* key_value_config*/);
-
- // Sort the packets in the window. Should be redundant,
- // but then almost no cost.
- bool enable_sort = false;
-
- // Cap the trendline slope based on the minimum delay seen
- // in the beginning_packets and end_packets respectively.
- bool enable_cap = false;
- unsigned beginning_packets = 7;
- unsigned end_packets = 7;
- double cap_uncertainty = 0.0;
-
- // Size (in packets) of the window.
- unsigned window_size = kDefaultTrendlineWindowSize;
-
- // std::unique_ptr<StructParametersParser> Parser();
-};
-
-class TrendlineEstimator /*: public DelayIncreaseDetectorInterface */ {
- public:
- TrendlineEstimator(/*const WebRtcKeyValueConfig* key_value_config,
- NetworkStatePredictor* network_state_predictor*/);
-
- ~TrendlineEstimator();
-
- // Update the estimator with a new sample. The deltas should represent deltas
- // between timestamp groups as defined by the InterArrival class.
- void Update(double recv_delta_ms, double send_delta_ms, int64_t send_time_ms,
- int64_t arrival_time_ms, size_t packet_size,
- bool calculated_deltas);
-
- void UpdateTrendline(double recv_delta_ms, double send_delta_ms,
- int64_t send_time_ms, int64_t arrival_time_ms,
- size_t packet_size);
-
- BandwidthUsage State() const;
-
- struct PacketTiming {
- PacketTiming(double arrival_time_ms, double smoothed_delay_ms,
- double raw_delay_ms)
- : arrival_time_ms(arrival_time_ms),
- smoothed_delay_ms(smoothed_delay_ms),
- raw_delay_ms(raw_delay_ms) {}
- double arrival_time_ms;
- double smoothed_delay_ms;
- double raw_delay_ms;
- };
-
- private:
- // friend class GoogCcStatePrinter;
- void Detect(double trend, double ts_delta, int64_t now_ms);
-
- void UpdateThreshold(double modified_offset, int64_t now_ms);
-
- // Parameters.
- TrendlineEstimatorSettings settings_;
- const double smoothing_coef_;
- const double threshold_gain_;
- // Used by the existing threshold.
- int num_of_deltas_;
- // Keep the arrival times small by using the change from the first packet.
- int64_t first_arrival_time_ms_;
- // Exponential backoff filtering.
- double accumulated_delay_;
- double smoothed_delay_;
- // Linear least squares regression.
- std::deque<PacketTiming> delay_hist_;
-
- const double k_up_;
- const double k_down_;
- double overusing_time_threshold_;
- double threshold_;
- double prev_modified_trend_;
- int64_t last_update_ms_;
- double prev_trend_;
- double time_over_using_;
- int overuse_counter_;
- BandwidthUsage hypothesis_;
- // BandwidthUsage hypothesis_predicted_;
- // NetworkStatePredictor* network_state_predictor_;
-
- // RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator);
-};
-
-} // namespace rtc
-
-} // end namespace protocol
-
-} // end namespace transport
-#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_
diff --git a/libtransport/src/protocols/rtc_data_path.cc b/libtransport/src/protocols/rtc_data_path.cc
deleted file mode 100644
index 30644e939..000000000
--- a/libtransport/src/protocols/rtc_data_path.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <protocols/rtc_data_path.h>
-
-#include <cfloat>
-#include <chrono>
-
-#define MAX_ROUNDS_WITHOUT_PKTS 10 // 2sec
-
-namespace transport {
-
-namespace protocol {
-
-RTCDataPath::RTCDataPath()
- : min_rtt(UINT_MAX),
- prev_min_rtt(UINT_MAX),
- min_owd(INT_MAX), // this is computed like in LEDBAT, so it is not the
- // real OWD, but the measured one, that depends on the
- // clock of sender and receiver. the only meaningful
- // value is is the queueing delay. for this reason we
- // keep both RTT (for the windowd calculation) and OWD
- // (for congestion/quality control)
- prev_min_owd(INT_MAX),
- avg_owd(0.0),
- queuing_delay(DBL_MAX),
- lastRecvSeq_(0),
- lastRecvTime_(0),
- avg_inter_arrival_(DBL_MAX),
- received_nacks_(false),
- received_packets_(false),
- rounds_without_packets_(0),
- RTThistory_(HISTORY_LEN),
- OWDhistory_(HISTORY_LEN){};
-
-void RTCDataPath::insertRttSample(uint64_t rtt) {
- // for the rtt we only keep track of the min one
- if (rtt < min_rtt) min_rtt = rtt;
-}
-
-void RTCDataPath::insertOwdSample(int64_t owd) {
- // for owd we use both min and avg
- if (owd < min_owd) min_owd = owd;
-
- if (avg_owd != DBL_MAX)
- avg_owd = (avg_owd * (1 - ALPHA_RTC)) + (owd * ALPHA_RTC);
- else {
- avg_owd = owd;
- }
-
- // owd is computed only for valid data packets so we count only
- // this for decide if we recevie traffic or not
- received_packets_ = true;
-}
-
-void RTCDataPath::computeInterArrivalGap(uint32_t segmentNumber) {
- // got packet in sequence, compute gap
- if (lastRecvSeq_ == (segmentNumber - 1)) {
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- uint64_t delta = now - lastRecvTime_;
- lastRecvSeq_ = segmentNumber;
- lastRecvTime_ = now;
- if (avg_inter_arrival_ == DBL_MAX)
- avg_inter_arrival_ = delta;
- else
- avg_inter_arrival_ =
- (avg_inter_arrival_ * (1 - ALPHA_RTC)) + (delta * ALPHA_RTC);
- return;
- }
-
- // ooo packet, update the stasts if needed
- if (lastRecvSeq_ <= segmentNumber) {
- lastRecvSeq_ = segmentNumber;
- lastRecvTime_ = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch())
- .count();
- }
-}
-
-void RTCDataPath::receivedNack() { received_nacks_ = true; }
-
-double RTCDataPath::getInterArrivalGap() {
- if (avg_inter_arrival_ == DBL_MAX) return 0;
- return avg_inter_arrival_;
-}
-
-bool RTCDataPath::isActive() {
- if (received_nacks_ && rounds_without_packets_ < MAX_ROUNDS_WITHOUT_PKTS)
- return true;
- return false;
-}
-
-void RTCDataPath::roundEnd() {
- // reset min_rtt and add it to the history
- if (min_rtt != UINT_MAX) {
- prev_min_rtt = min_rtt;
- } else {
- // this may happen if we do not receive any packet
- // from this path in the last round. in this case
- // we use the measure from the previuos round
- min_rtt = prev_min_rtt;
- }
-
- if (min_rtt == 0) min_rtt = 1;
-
- RTThistory_.pushBack(min_rtt);
- min_rtt = UINT_MAX;
-
- // do the same for min owd
- if (min_owd != INT_MAX) {
- prev_min_owd = min_owd;
- } else {
- min_owd = prev_min_owd;
- }
-
- if (min_owd != INT_MAX) {
- OWDhistory_.pushBack(min_owd);
- min_owd = INT_MAX;
-
- // compute queuing delay
- queuing_delay = avg_owd - getMinOwd();
-
- } else {
- queuing_delay = 0.0;
- }
-
- if (!received_packets_)
- rounds_without_packets_++;
- else
- rounds_without_packets_ = 0;
- received_packets_ = false;
-}
-
-double RTCDataPath::getQueuingDealy() { return queuing_delay; }
-
-uint64_t RTCDataPath::getMinRtt() { return RTThistory_.begin(); }
-
-int64_t RTCDataPath::getMinOwd() { return OWDhistory_.begin(); }
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/rtc_data_path.h b/libtransport/src/protocols/rtc_data_path.h
deleted file mode 100644
index 9076b355f..000000000
--- a/libtransport/src/protocols/rtc_data_path.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <climits>
-
-#include <utils/min_filter.h>
-
-#define ALPHA_RTC 0.125
-#define HISTORY_LEN 20 // 4 sec
-
-namespace transport {
-
-namespace protocol {
-
-class RTCDataPath {
- public:
- RTCDataPath();
-
- public:
- void insertRttSample(uint64_t rtt);
- void insertOwdSample(int64_t owd);
- void computeInterArrivalGap(uint32_t segmentNumber);
- void receivedNack();
-
- uint64_t getMinRtt();
- double getQueuingDealy();
- double getInterArrivalGap();
- bool isActive();
-
- void roundEnd();
-
- private:
- int64_t getMinOwd();
-
- uint64_t min_rtt;
- uint64_t prev_min_rtt;
-
- int64_t min_owd;
- int64_t prev_min_owd;
-
- double avg_owd;
-
- double queuing_delay;
-
- uint32_t lastRecvSeq_;
- uint64_t lastRecvTime_;
- double avg_inter_arrival_;
-
- // flags to check if a path is active
- // we considere a path active if it reaches a producer
- //(not a cache) --aka we got at least one nack on this path--
- // and if we receives packets
- bool received_nacks_;
- bool received_packets_;
- uint8_t rounds_without_packets_; // if we don't get any packet
- // for MAX_ROUNDS_WITHOUT_PKTS
- // we consider the path inactive
-
- utils::MinFilter<uint64_t> RTThistory_;
- utils::MinFilter<int64_t> OWDhistory_;
-};
-
-} // namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/transport_protocol.cc b/libtransport/src/protocols/transport_protocol.cc
index 611c39212..d6954ac37 100644
--- a/libtransport/src/protocols/transport_protocol.cc
+++ b/libtransport/src/protocols/transport_protocol.cc
@@ -24,12 +24,11 @@ namespace protocol {
using namespace interface;
TransportProtocol::TransportProtocol(implementation::ConsumerSocket *icn_socket,
- Reassembly *reassembly_protocol)
+ Indexer *indexer, Reassembly *reassembly)
: socket_(icn_socket),
- reassembly_protocol_(reassembly_protocol),
- index_manager_(
- std::make_unique<IndexManager>(socket_, this, reassembly_protocol)),
- is_running_(false),
+ indexer_verifier_(indexer),
+ reassembly_(reassembly),
+ fec_decoder_(nullptr),
is_first_(false),
on_interest_retransmission_(VOID_HANDLER),
on_interest_output_(VOID_HANDLER),
@@ -37,9 +36,17 @@ TransportProtocol::TransportProtocol(implementation::ConsumerSocket *icn_socket,
on_interest_satisfied_(VOID_HANDLER),
on_content_object_input_(VOID_HANDLER),
stats_summary_(VOID_HANDLER),
- on_payload_(VOID_HANDLER) {
+ on_payload_(VOID_HANDLER),
+ fec_type_(fec::FECType::UNKNOWN),
+ is_running_(false) {
socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal_);
socket_->getSocketOption(OtherOptions::STATISTICS, &stats_);
+
+ // Set this transport protocol as portal's consumer callback
+ portal_->setConsumerCallback(this);
+
+ indexer_verifier_->setReassembly(reassembly_.get());
+ reassembly->setIndexer(indexer_verifier_.get());
}
int TransportProtocol::start() {
@@ -69,6 +76,7 @@ int TransportProtocol::start() {
// Reset the protocol state machine
reset();
+
// Schedule next interests
scheduleNextInterests();
@@ -99,15 +107,27 @@ void TransportProtocol::stop() {
}
void TransportProtocol::resume() {
- if (is_running_) return;
+ if (isRunning()) return;
is_running_ = true;
scheduleNextInterests();
- portal_->runEventsLoop();
+ if (!is_async_) {
+ // Start Event loop
+ portal_->runEventsLoop();
- is_running_ = false;
+ // Not running anymore
+ is_running_ = false;
+ }
+}
+
+void TransportProtocol::reset() {
+ reassembly_->reInitialize();
+ indexer_verifier_->reset();
+ if (fec_decoder_) {
+ fec_decoder_->reset();
+ }
}
void TransportProtocol::onContentReassembled(std::error_code ec) {
@@ -127,6 +147,70 @@ void TransportProtocol::onContentReassembled(std::error_code ec) {
}
}
+void TransportProtocol::sendInterest(
+ const Name &interest_name,
+ std::array<uint32_t, MAX_AGGREGATED_INTEREST> *additional_suffixes,
+ uint32_t len) {
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending interest for name " << interest_name;
+
+ auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
+ interest->setName(interest_name);
+
+ for (uint32_t i = 0; i < len; i++) {
+ interest->appendSuffix(additional_suffixes->at(i));
+ }
+
+ uint32_t lifetime = default_values::interest_lifetime;
+ socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
+ lifetime);
+ interest->setLifetime(uint32_t(lifetime));
+
+ if (*on_interest_output_) {
+ (*on_interest_output_)(*socket_->getInterface(), *interest);
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(!isRunning() && !is_first_)) {
+ return;
+ }
+
+ portal_->sendInterest(std::move(interest));
+}
+
+void TransportProtocol::onTimeout(Interest::Ptr &i, const Name &n) {
+ if (TRANSPORT_EXPECT_FALSE(!isRunning())) {
+ return;
+ }
+
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Timeout on content " << n;
+
+ onInterestTimeout(i, n);
+}
+
+void TransportProtocol::onContentObject(Interest &i, ContentObject &c) {
+ // Check whether it makes sense to continue
+ if (TRANSPORT_EXPECT_FALSE(!isRunning())) {
+ return;
+ }
+
+ // Call transport protocol function
+ std::error_code ec;
+ onContentObjectReceived(i, c, ec);
+
+ // Call reassemble function, if packet is eligible for reassemblying
+ bool reassemble = false;
+ if (!ec) {
+ reassemble = true;
+ }
+
+ // Perform verification and update indexer. This step may be performed offline
+ // - i.e. we may not get a result here (e.g. we use manifest). Verification
+ // failures in that case will be handled in the onPacketDropped function.
+ // XXX This step should be done before calling onContentObjectReceived, but
+ // for now we do it here since currently the indexer does not need manifests
+ // to move forward.
+ indexer_verifier_->onContentObject(i, c, reassemble);
+}
+
} // end namespace protocol
} // end namespace transport
diff --git a/libtransport/src/protocols/transport_protocol.h b/libtransport/src/protocols/transport_protocol.h
index 124c57122..1008a238b 100644
--- a/libtransport/src/protocols/transport_protocol.h
+++ b/libtransport/src/protocols/transport_protocol.h
@@ -21,9 +21,11 @@
#include <hicn/transport/utils/object_pool.h>
#include <implementation/socket.h>
#include <protocols/data_processing_events.h>
+#include <protocols/fec_base.h>
#include <protocols/indexer.h>
#include <protocols/reassembly.h>
+#include <array>
#include <atomic>
namespace transport {
@@ -36,12 +38,6 @@ class IndexVerificationManager;
using ReadCallback = interface::ConsumerSocket::ReadCallback;
-class TransportProtocolCallback {
- virtual void onContentObject(const core::Interest &interest,
- const core::ContentObject &content_object) = 0;
- virtual void onTimeout(const core::Interest &interest) = 0;
-};
-
class TransportProtocol : public core::Portal::ConsumerCallback,
public ContentObjectProcessingEventCallback {
static constexpr std::size_t interest_pool_size = 4096;
@@ -50,7 +46,7 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
public:
TransportProtocol(implementation::ConsumerSocket *icn_socket,
- Reassembly *reassembly_protocol);
+ Indexer *indexer, Reassembly *reassembly);
virtual ~TransportProtocol() = default;
@@ -62,27 +58,70 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
virtual void resume();
+ /**
+ * @brief Get the size of any additional header added by the specific
+ * transport implementation.
+ *
+ * @return The header length in bytes.
+ */
+ virtual std::size_t transportHeaderLength() { return 0; }
+
virtual void scheduleNextInterests() = 0;
// Events generated by the indexing
virtual void onContentReassembled(std::error_code ec);
virtual void onPacketDropped(Interest &interest,
- ContentObject &content_object) override = 0;
+ ContentObject &content_object,
+ const std::error_code &ec) override = 0;
virtual void onReassemblyFailed(std::uint32_t missing_segment) override = 0;
protected:
+ virtual void onContentObjectReceived(Interest &i, ContentObject &c,
+ std::error_code &ec) = 0;
+ virtual void onInterestTimeout(Interest::Ptr &i, const Name &n) = 0;
+
+ virtual void sendInterest(const Name &interest_name,
+ std::array<uint32_t, MAX_AGGREGATED_INTEREST>
+ *additional_suffixes = nullptr,
+ uint32_t len = 0);
+
+ template <typename FECHandler, typename AllocatorHandler>
+ void enableFEC(FECHandler &&fec_handler,
+ AllocatorHandler &&allocator_handler) {
+ if (!fec_decoder_) {
+ // Try to get FEC from environment
+ if (const char *fec_str = std::getenv("TRANSPORT_FEC_TYPE")) {
+ LOG(INFO) << "Using FEC " << fec_str;
+ fec_type_ = fec::FECUtils::fecTypeFromString(fec_str);
+ }
+
+ if (fec_type_ == fec::FECType::UNKNOWN) {
+ return;
+ }
+
+ fec_decoder_ = fec::FECUtils::getDecoder(
+ fec_type_, indexer_verifier_->getFirstSuffix());
+ fec_decoder_->setFECCallback(std::forward<FECHandler>(fec_handler));
+ fec_decoder_->setBufferCallback(
+ std::forward<AllocatorHandler>(allocator_handler));
+ indexer_verifier_->enableFec(fec_type_);
+ }
+ }
+
+ virtual void reset();
+
+ private:
// Consumer Callback
- virtual void reset() = 0;
- virtual void onContentObject(Interest &i, ContentObject &c) override = 0;
- virtual void onTimeout(Interest::Ptr &&i) override = 0;
- virtual void onError(std::error_code ec) override {}
+ void onContentObject(Interest &i, ContentObject &c) override;
+ void onTimeout(Interest::Ptr &i, const Name &n) override;
+ void onError(std::error_code ec) override {}
protected:
implementation::ConsumerSocket *socket_;
- std::unique_ptr<Reassembly> reassembly_protocol_;
- std::unique_ptr<IndexManager> index_manager_;
+ std::unique_ptr<Indexer> indexer_verifier_;
+ std::unique_ptr<Reassembly> reassembly_;
+ std::unique_ptr<fec::ConsumerFEC> fec_decoder_;
std::shared_ptr<core::Portal> portal_;
- std::atomic<bool> is_running_;
// True if it si the first time we schedule an interest
std::atomic<bool> is_first_;
interface::TransportStatistics *stats_;
@@ -98,6 +137,11 @@ class TransportProtocol : public core::Portal::ConsumerCallback,
ReadCallback *on_payload_;
bool is_async_;
+
+ fec::FECType fec_type_;
+
+ private:
+ std::atomic<bool> is_running_;
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/verification_manager.cc b/libtransport/src/protocols/verification_manager.cc
deleted file mode 100644
index 8eedd6106..000000000
--- a/libtransport/src/protocols/verification_manager.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/interfaces/socket_consumer.h>
-#include <hicn/transport/security/verifier.h>
-
-#include <implementation/socket_consumer.h>
-#include <protocols/verification_manager.h>
-
-namespace transport {
-
-namespace protocol {
-
-interface::VerificationPolicy SignatureVerificationManager::onPacketToVerify(
- const Packet& packet) {
- using namespace interface;
-
- bool verify_signature = false, key_content = false;
- VerificationPolicy ret = VerificationPolicy::DROP_PACKET;
-
- icn_socket_->getSocketOption(GeneralTransportOptions::VERIFY_SIGNATURE,
- verify_signature);
- icn_socket_->getSocketOption(GeneralTransportOptions::KEY_CONTENT,
- key_content);
-
- if (!verify_signature) {
- return VerificationPolicy::ACCEPT_PACKET;
- }
-
- if (key_content) {
- key_packets_.push(copyPacket(packet));
- return VerificationPolicy::ACCEPT_PACKET;
- } else if (!key_packets_.empty()) {
- std::queue<ContentObjectPtr>().swap(key_packets_);
- }
-
- ConsumerContentObjectVerificationFailedCallback*
- verification_failed_callback = VOID_HANDLER;
- icn_socket_->getSocketOption(ConsumerCallbacksOptions::VERIFICATION_FAILED,
- &verification_failed_callback);
-
- if (!verification_failed_callback) {
- throw errors::RuntimeException(
- "No verification failed callback provided by application. "
- "Aborting.");
- }
-
- std::shared_ptr<utils::Verifier> verifier;
- icn_socket_->getSocketOption(GeneralTransportOptions::VERIFIER, verifier);
-
- if (TRANSPORT_EXPECT_FALSE(!verifier)) {
- ret = (*verification_failed_callback)(
- *icn_socket_->getInterface(),
- dynamic_cast<const ContentObject&>(packet),
- make_error_code(protocol_error::no_verifier_provided));
- return ret;
- }
-
- if (!verifier->verify(packet)) {
- ret = (*verification_failed_callback)(
- *icn_socket_->getInterface(),
- dynamic_cast<const ContentObject&>(packet),
- make_error_code(protocol_error::signature_verification_failed));
- } else {
- ret = VerificationPolicy::ACCEPT_PACKET;
- }
-
- return ret;
-}
-
-bool SignatureVerificationManager::onKeyToVerify() {
- if (TRANSPORT_EXPECT_FALSE(key_packets_.empty())) {
- throw errors::RuntimeException("No key to verify.");
- }
-
- while (!key_packets_.empty()) {
- ContentObjectPtr packet_to_verify = key_packets_.front();
- key_packets_.pop();
- if (onPacketToVerify(*packet_to_verify) !=
- VerificationPolicy::ACCEPT_PACKET)
- return false;
- }
-
- return true;
-}
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/protocols/verification_manager.h b/libtransport/src/protocols/verification_manager.h
deleted file mode 100644
index 7d8a00a65..000000000
--- a/libtransport/src/protocols/verification_manager.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <hicn/transport/interfaces/callbacks.h>
-#include <hicn/transport/interfaces/verification_policy.h>
-
-#include <hicn/transport/core/content_object.h>
-
-#include <protocols/errors.h>
-
-#include <queue>
-
-namespace transport {
-
-namespace interface {
-class ConsumerSocket;
-}
-
-namespace protocol {
-
-using Packet = core::Packet;
-using interface::VerificationPolicy;
-using ContentObjectPtr = std::shared_ptr<core::ContentObject>;
-
-class VerificationManager {
- public:
- virtual ~VerificationManager() = default;
- virtual VerificationPolicy onPacketToVerify(const Packet& packet) = 0;
- virtual bool onKeyToVerify() { return false; }
-};
-
-class SignatureVerificationManager : public VerificationManager {
- public:
- SignatureVerificationManager(implementation::ConsumerSocket* icn_socket)
- : icn_socket_(icn_socket), key_packets_() {}
-
- interface::VerificationPolicy onPacketToVerify(const Packet& packet) override;
- bool onKeyToVerify() override;
-
- private:
- implementation::ConsumerSocket* icn_socket_;
- std::queue<ContentObjectPtr> key_packets_;
-
- ContentObjectPtr copyPacket(const Packet& packet) {
- std::shared_ptr<utils::MemBuf> packet_copy =
- packet.acquireMemBufReference();
- ContentObjectPtr content_object_copy =
- std::make_shared<core::ContentObject>(std::move(packet_copy));
- std::unique_ptr<utils::MemBuf> payload_copy = packet.getPayload();
- content_object_copy->appendPayload(std::move(payload_copy));
- return content_object_copy;
- }
-};
-
-} // end namespace protocol
-
-} // end namespace transport
diff --git a/libtransport/src/security/identity.cc b/libtransport/src/security/identity.cc
deleted file mode 100644
index d7a08f7b5..000000000
--- a/libtransport/src/security/identity.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/security/identity.h>
-
-extern "C" {
-#include <parc/security/parc_PublicKeySigner.h>
-#include <parc/security/parc_Security.h>
-}
-
-namespace utils {
-
-Identity::Identity(const std::string &keystore_name,
- const std::string &keystore_password, CryptoSuite suite,
- unsigned int key_length, unsigned int validity_days,
- const std::string &subject_name) {
- parcSecurity_Init();
-
- bool success = parcPkcs12KeyStore_CreateFile(
- keystore_name.c_str(), keystore_password.c_str(), subject_name.c_str(),
- parcCryptoSuite_GetSigningAlgorithm(static_cast<PARCCryptoSuite>(suite)),
- key_length, validity_days);
-
- parcAssertTrue(
- success,
- "parcPkcs12KeyStore_CreateFile('%s', '%s', '%s', %d, %d) failed.",
- keystore_name.c_str(), keystore_password.c_str(), subject_name.c_str(),
- static_cast<int>(key_length), validity_days);
-
- PARCIdentityFile *identity_file =
- parcIdentityFile_Create(keystore_name.c_str(), keystore_password.c_str());
-
- identity_ =
- parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
-
- PARCSigner *signer = parcIdentity_CreateSigner(
- identity_,
- parcCryptoSuite_GetCryptoHash(static_cast<PARCCryptoSuite>(suite)));
-
- signer_ = std::make_shared<Signer>(signer, suite);
-
- parcSigner_Release(&signer);
- parcIdentityFile_Release(&identity_file);
-}
-
-Identity::Identity(const Identity &other)
- : signer_(other.signer_), hash_algorithm_(other.hash_algorithm_) {
- parcSecurity_Init();
- identity_ = parcIdentity_Acquire(other.identity_);
-}
-
-Identity Identity::generateIdentity(const std::string &subject_name) {
- std::string keystore_name = "keystore";
- std::string keystore_password = "password";
- std::size_t key_length = 1024;
- unsigned int validity_days = 30;
- CryptoSuite suite = CryptoSuite::RSA_SHA256;
-
- return utils::Identity(keystore_name, keystore_password, suite,
- (unsigned int)key_length, validity_days, subject_name);
-}
-
-Identity::Identity(std::string &file_name, std::string &password,
- utils::CryptoHashType hash_algorithm)
- : hash_algorithm_(hash_algorithm) {
- parcSecurity_Init();
-
- PARCIdentityFile *identity_file =
- parcIdentityFile_Create(file_name.c_str(), password.c_str());
-
- identity_ =
- parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
-
- PARCSigner *signer = parcIdentity_CreateSigner(
- identity_, static_cast<PARCCryptoHashType>(hash_algorithm));
-
- signer_ = std::make_shared<Signer>(
- signer, CryptoSuite(parcSigner_GetCryptoSuite(signer)));
-
- parcSigner_Release(&signer);
- parcIdentityFile_Release(&identity_file);
-}
-
-Identity::~Identity() {
- parcIdentity_Release(&identity_);
- parcSecurity_Fini();
-}
-
-std::string Identity::getFileName() {
- return std::string(parcIdentity_GetFileName(identity_));
-}
-
-std::string Identity::getPassword() {
- return std::string(parcIdentity_GetPassWord(identity_));
-}
-
-std::shared_ptr<Signer> Identity::getSigner() { return signer_; }
-
-size_t Identity::getSignatureLength() const {
- return signer_->getSignatureLength();
-}
-
-} // namespace utils
diff --git a/libtransport/src/security/signer.cc b/libtransport/src/security/signer.cc
deleted file mode 100644
index aa2751611..000000000
--- a/libtransport/src/security/signer.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Copyright 2017 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/errors/malformed_ahpacket_exception.h>
-#include <hicn/transport/security/key_id.h>
-#include <hicn/transport/security/signer.h>
-#include <hicn/transport/utils/membuf.h>
-
-extern "C" {
-#ifndef _WIN32
-TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
-#endif
-#include <hicn/hicn.h>
-#include <parc/security/parc_PublicKeySigner.h>
-#include <parc/security/parc_Security.h>
-#include <parc/security/parc_SymmetricKeySigner.h>
-}
-
-#include <chrono>
-
-#define ALLOW_UNALIGNED_READS 1
-
-namespace utils {
-
-Signer::Signer(PARCKeyStore *keyStore, CryptoSuite suite) {
- parcSecurity_Init();
-
- switch (suite) {
- case CryptoSuite::DSA_SHA256:
- case CryptoSuite::RSA_SHA256:
- case CryptoSuite::RSA_SHA512:
- case CryptoSuite::ECDSA_256K1: {
- this->signer_ =
- parcSigner_Create(parcPublicKeySigner_Create(
- keyStore, static_cast<PARCCryptoSuite>(suite)),
- PARCPublicKeySignerAsSigner);
- break;
- }
- case CryptoSuite::HMAC_SHA256:
- case CryptoSuite::HMAC_SHA512: {
- this->signer_ =
- parcSigner_Create(parcSymmetricKeySigner_Create(
- (PARCSymmetricKeyStore *)keyStore,
- parcCryptoSuite_GetCryptoHash(
- static_cast<PARCCryptoSuite>(suite))),
- PARCSymmetricKeySignerAsSigner);
- break;
- }
- default: { return; }
- }
-
- suite_ = suite;
- key_id_ = parcSigner_CreateKeyId(this->signer_);
- signature_length_ = parcSigner_GetSignatureSize(this->signer_);
-}
-
-Signer::Signer(const std::string &passphrase, CryptoSuite suite) {
- parcSecurity_Init();
-
- switch (suite) {
- case CryptoSuite::HMAC_SHA256:
- case CryptoSuite::HMAC_SHA512: {
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_PutString(composer, passphrase.c_str());
- PARCBuffer *key_buffer = parcBufferComposer_ProduceBuffer(composer);
- PARCSymmetricKeyStore *symmetricKeyStore =
- parcSymmetricKeyStore_Create(key_buffer);
- this->signer_ = parcSigner_Create(
- parcSymmetricKeySigner_Create(
- symmetricKeyStore, parcCryptoSuite_GetCryptoHash(
- static_cast<PARCCryptoSuite>(suite))),
- PARCSymmetricKeySignerAsSigner);
-
- parcBuffer_Release(&key_buffer);
- parcSymmetricKeyStore_Release(&symmetricKeyStore);
- parcBufferComposer_Release(&composer);
- break;
- }
- default: { return; }
- }
-
- suite_ = suite;
- key_id_ = parcSigner_CreateKeyId(this->signer_);
- signature_length_ = parcSigner_GetSignatureSize(this->signer_);
-}
-
-Signer::Signer(const PARCSigner *signer, CryptoSuite suite)
- : suite_(suite),
- signer_(parcSigner_Acquire(signer)),
- key_id_(parcSigner_CreateKeyId(this->signer_)),
- signature_length_(parcSigner_GetSignatureSize(this->signer_)) {
- parcSecurity_Init();
-}
-
-Signer::Signer(const PARCSigner *signer)
- : Signer(signer, CryptoSuite::UNKNOWN) {}
-
-Signer::~Signer() {
- if (signer_) parcSigner_Release(&signer_);
- if (key_id_) parcKeyId_Release(&key_id_);
- parcSecurity_Fini();
-}
-
-void Signer::sign(Packet &packet) {
- /* header chain points to the IP + TCP hicn header + AH Header */
- MemBuf *header_chain = packet.header_head_;
- MemBuf *payload_chain = packet.payload_head_;
- uint8_t *hicn_packet = (uint8_t *)header_chain->writableData();
- Packet::Format format = packet.getFormat();
-
- if (!(format & HFO_AH)) {
- throw errors::MalformedAHPacketException();
- }
-
- packet.setSignatureSize(signature_length_);
-
- /* Copy IP+TCP/ICMP header before zeroing them */
- hicn_header_t header_copy;
- hicn_packet_copy_header(format, (const hicn_header_t *)packet.packet_start_,
- &header_copy, false);
-
- std::size_t header_len = Packet::getHeaderSizeFromFormat(format);
-
- packet.resetForHash();
-
- /* Fill the hicn_ah header */
- using namespace std::chrono;
- auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch())
- .count();
- packet.setSignatureTimestamp(now);
- packet.setValidationAlgorithm(suite_);
-
- KeyId key_id;
- key_id.first = (uint8_t *)parcBuffer_Overlay(
- (PARCBuffer *)parcKeyId_GetKeyId(this->key_id_), 0);
- packet.setKeyId(key_id);
-
- /* Calculate hash */
- CryptoHasher hasher(parcSigner_GetCryptoHasher(signer_));
- hasher.init();
- hasher.updateBytes(hicn_packet, header_len + signature_length_);
-
- for (MemBuf *current = payload_chain; current != header_chain;
- current = current->next()) {
- hasher.updateBytes(current->data(), current->length());
- }
-
- CryptoHash hash = hasher.finalize();
- PARCSignature *signature = parcSigner_SignDigestNoAlloc(
- this->signer_, hash.hash_, packet.getSignature(),
- (uint32_t)signature_length_);
- PARCBuffer *buffer = parcSignature_GetSignature(signature);
- size_t bytes_len = parcBuffer_Remaining(buffer);
-
- if (bytes_len > signature_length_) {
- throw errors::MalformedAHPacketException();
- }
-
- hicn_packet_copy_header(format, &header_copy,
- (hicn_header_t *)packet.packet_start_, false);
-
- parcSignature_Release(&signature);
-}
-
-size_t Signer::getSignatureLength() { return signature_length_; }
-
-PARCKeyStore *Signer::getKeyStore() {
- return parcSigner_GetKeyStore(this->signer_);
-}
-
-} // namespace utils
diff --git a/libtransport/src/security/verifier.cc b/libtransport/src/security/verifier.cc
deleted file mode 100644
index 4f6a2be4c..000000000
--- a/libtransport/src/security/verifier.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/core/packet.h>
-#include <hicn/transport/errors/malformed_ahpacket_exception.h>
-#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/security/key_id.h>
-#include <hicn/transport/security/verifier.h>
-#include <hicn/transport/utils/log.h>
-
-extern "C" {
-#ifndef _WIN32
-TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
-#endif
-#include <hicn/hicn.h>
-}
-
-#include <sys/stat.h>
-
-namespace utils {
-
-TRANSPORT_ALWAYS_INLINE bool file_exists(const std::string &name) {
- struct stat buffer;
- return (stat(name.c_str(), &buffer) == 0);
-}
-
-Verifier::Verifier() {
- parcSecurity_Init();
- PARCInMemoryVerifier *in_memory_verifier = parcInMemoryVerifier_Create();
- this->verifier_ =
- parcVerifier_Create(in_memory_verifier, PARCInMemoryVerifierAsVerifier);
- parcInMemoryVerifier_Release(&in_memory_verifier);
-}
-
-Verifier::~Verifier() {
- if (signer_) parcSigner_Release(&signer_);
- if (verifier_) parcVerifier_Release(&verifier_);
- parcSecurity_Fini();
-}
-
-/*
- * TODO: Unsupported in libparc
- */
-bool Verifier::hasKey(PARCKeyId *key_id) { return false; }
-
-/*
- * TODO: Signal errors without trap.
- */
-bool Verifier::addKey(PARCKey *key) {
- parcVerifier_AddKey(this->verifier_, key);
- return true;
-}
-
-PARCKeyId *Verifier::addKeyFromPassphrase(const std::string &passphrase,
- CryptoSuite suite) {
- PARCBufferComposer *composer = parcBufferComposer_Create();
- parcBufferComposer_PutString(composer, passphrase.c_str());
- PARCBuffer *key_buffer = parcBufferComposer_ProduceBuffer(composer);
-
- PARCSymmetricKeyStore *symmetricKeyStore =
- parcSymmetricKeyStore_Create(key_buffer);
- signer_ = parcSigner_Create(
- parcSymmetricKeySigner_Create(
- symmetricKeyStore,
- parcCryptoSuite_GetCryptoHash(static_cast<PARCCryptoSuite>(suite))),
- PARCSymmetricKeySignerAsSigner);
-
- PARCKeyId *key_id = parcSigner_CreateKeyId(signer_);
- PARCKey *key = parcKey_CreateFromSymmetricKey(
- key_id, parcSigner_GetSigningAlgorithm(signer_), key_buffer);
-
- addKey(key);
-
- parcKey_Release(&key);
- parcSymmetricKeyStore_Release(&symmetricKeyStore);
- parcBuffer_Release(&key_buffer);
- parcBufferComposer_Release(&composer);
-
- return key_id;
-}
-
-PARCKeyId *Verifier::addKeyFromCertificate(const std::string &file_name) {
- PARCCertificateFactory *factory = parcCertificateFactory_Create(
- PARCCertificateType_X509, PARCContainerEncoding_PEM);
- parcAssertNotNull(factory, "Expected non-NULL factory");
-
- if (!file_exists(file_name)) {
- TRANSPORT_LOGW("Warning! The certificate %s file does not exist",
- file_name.c_str());
- return nullptr;
- }
-
- PARCCertificate *certificate =
- parcCertificateFactory_CreateCertificateFromFile(
- factory, (char *)file_name.c_str(), NULL);
- PARCBuffer *derEncodedVersion =
- parcCertificate_GetDEREncodedPublicKey(certificate);
- PARCCryptoHash *keyDigest = parcCertificate_GetPublicKeyDigest(certificate);
-
- PARCKeyId *key_id = parcKeyId_Create(parcCryptoHash_GetDigest(keyDigest));
- PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(
- key_id, PARCSigningAlgorithm_RSA, derEncodedVersion);
-
- addKey(key);
-
- parcKey_Release(&key);
- parcCertificate_Release(&certificate);
- parcCertificateFactory_Release(&factory);
-
- return key_id;
-}
-
-int Verifier::verify(const Packet &packet) {
- /* Initialize packet.payload_head_ */
- const_cast<Packet *>(&packet)->separateHeaderPayload();
-
- bool valid = false;
- Packet::Format format = packet.getFormat();
-
- if (!(format & HFO_AH)) {
- throw errors::MalformedAHPacketException();
- }
-
- /* Copy IP+TCP/ICMP header before zeroing them */
- hicn_header_t header_copy;
- hicn_packet_copy_header(format, (const hicn_header_t *)packet.packet_start_,
- &header_copy, false);
-
- /* Get crypto suite */
- PARCCryptoSuite suite =
- static_cast<PARCCryptoSuite>(packet.getValidationAlgorithm());
- PARCCryptoHashType hashtype = parcCryptoSuite_GetCryptoHash(suite);
-
- /* Fetch the key that we will use to verify the signature */
- KeyId _key_id = packet.getKeyId();
- PARCBuffer *buffer =
- parcBuffer_Wrap(_key_id.first, _key_id.second, 0, _key_id.second);
- PARCKeyId *key_id = parcKeyId_Create(buffer);
- parcBuffer_Release(&buffer);
-
- /* Fetch signature */
- int ah_payload_len = (int)packet.getSignatureSize();
- uint8_t *_signature = packet.getSignature();
- uint8_t *signature = new uint8_t[ah_payload_len];
- /* TODO Remove signature copy at this point, by not setting to zero */
- /* the validation payload. */
- std::memcpy(signature, _signature, ah_payload_len);
-
- /* Prepare local computation of the signature based on the crypto suite */
- PARCCryptoHasher *hasher_ptr = nullptr;
- switch (CryptoSuite(suite)) {
- case CryptoSuite::DSA_SHA256:
- case CryptoSuite::RSA_SHA256:
- case CryptoSuite::RSA_SHA512:
- case CryptoSuite::ECDSA_256K1: {
- hasher_ptr = parcVerifier_GetCryptoHasher(verifier_, key_id, hashtype);
- break;
- }
- case CryptoSuite::HMAC_SHA256:
- case CryptoSuite::HMAC_SHA512: {
- if (!signer_) return false;
- hasher_ptr = parcSigner_GetCryptoHasher(signer_);
- break;
- }
- default: { return false; }
- }
-
- /* Compute the packet signature locally */
- CryptoHasher crypto_hasher(hasher_ptr);
- CryptoHash hash_computed_locally = getPacketHash(packet, crypto_hasher);
-
- /* Create a signature object from the raw packet signature */
- PARCBuffer *bits =
- parcBuffer_Wrap(signature, ah_payload_len, 0, ah_payload_len);
- parcBuffer_Rewind(bits);
-
- /* If the signature algo is ECDSA, the signature might be shorter than the
- * signature field */
- PARCSigningAlgorithm algo = parcCryptoSuite_GetSigningAlgorithm(suite);
- while (algo == PARCSigningAlgorithm_ECDSA && parcBuffer_HasRemaining(bits) &&
- parcBuffer_GetUint8(bits) == 0)
- ;
-
- if (algo == PARCSigningAlgorithm_ECDSA) {
- parcBuffer_SetPosition(bits, parcBuffer_Position(bits) - 1);
- }
-
- if (!parcBuffer_HasRemaining(bits)) {
- delete[] signature;
- parcKeyId_Release(&key_id);
- parcBuffer_Release(&bits);
- return valid;
- }
-
- PARCSignature *signatureToVerify = parcSignature_Create(
- parcCryptoSuite_GetSigningAlgorithm(suite), hashtype, bits);
-
- if (algo == PARCSigningAlgorithm_RSA) {
- parcBuffer_SetPosition(bits, 0);
- }
-
- /* Compare the packet signature to the locally computed one */
- valid = parcVerifier_VerifyDigestSignature(
- verifier_, key_id, hash_computed_locally.hash_, suite, signatureToVerify);
-
- /* Restore the fields that were reset */
- hicn_packet_copy_header(format, &header_copy,
- (hicn_header_t *)packet.packet_start_, false);
-
- delete[] signature;
- parcKeyId_Release(&key_id);
- parcBuffer_Release(&bits);
- parcSignature_Release(&signatureToVerify);
-
- return valid;
-}
-
-CryptoHash Verifier::getPacketHash(const Packet &packet,
- CryptoHasher &crypto_hasher) {
- MemBuf *header_chain = packet.header_head_;
- MemBuf *payload_chain = packet.payload_head_;
- Packet::Format format = packet.getFormat();
- int ah_payload_len = (int)packet.getSignatureSize();
- uint8_t *hicn_packet = header_chain->writableData();
- std::size_t header_len = Packet::getHeaderSizeFromFormat(format);
-
- /* Reset fields that should not appear in the signature */
- const_cast<Packet &>(packet).resetForHash();
- crypto_hasher.init().updateBytes(hicn_packet, header_len + ah_payload_len);
-
- for (MemBuf *current = payload_chain; current != header_chain;
- current = current->next()) {
- crypto_hasher.updateBytes(current->data(), current->length());
- }
-
- return crypto_hasher.finalize();
-}
-
-} // namespace utils
diff --git a/libtransport/src/test/CMakeLists.txt b/libtransport/src/test/CMakeLists.txt
index dd3d1d923..26fe7aee1 100644
--- a/libtransport/src/test/CMakeLists.txt
+++ b/libtransport/src/test/CMakeLists.txt
@@ -13,27 +13,40 @@
include(BuildMacros)
-list(APPEND TESTS
- test_auth
- test_consumer_producer_rtc
- test_core_manifest
- test_event_thread
- test_fec_reedsolomon
- test_interest
- test_packet
+list(APPEND TESTS_SRC
+ main.cc
+ test_auth.cc
+ test_consumer_producer_rtc.cc
+ test_core_manifest.cc
+ test_event_thread.cc
+ test_fec_reedsolomon.cc
+ test_indexer.cc
+ test_interest.cc
+ test_packet.cc
)
-foreach(test ${TESTS})
- build_executable(${test}
- NO_INSTALL
- SOURCES ${test}.cc
- LINK_LIBRARIES ${LIBTRANSPORT_SHARED} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
- DEPENDS gtest ${LIBTRANSPORT_SHARED}
- COMPONENT lib${LIBTRANSPORT}
- DEFINITIONS "${COMPILER_DEFINITIONS}"
- LINK_FLAGS ${LINK_FLAGS}
- )
+if (ENABLE_RELY)
+ list(APPEND TESTS_SRC
+ test_fec_rely_wrapper.cc
+ )
+endif()
- add_test_internal(${test})
-endforeach()
+build_executable(unit_tests
+ NO_INSTALL
+ SOURCES ${TESTS_SRC}
+ LINK_LIBRARIES
+ ${LIBRARIES}
+ ${LIBTRANSPORT_STATIC}
+ ${GTEST_LIBRARIES}
+ INCLUDE_DIRS
+ ${LIBTRANSPORT_INCLUDE_DIRS}
+ ${LIBHICN_INCLUDE_DIRS}
+ ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ ${GTEST_INCLUDE_DIRS}
+ DEPENDS gtest ${LIBTRANSPORT_SHARED}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ DEFINITIONS "${COMPILER_DEFINITIONS}"
+ LINK_FLAGS ${LINK_FLAGS}
+)
+
+add_test_internal(unit_tests)
diff --git a/libtransport/src/test/fec_reed_solomon.cc b/libtransport/src/test/fec_reed_solomon.cc
deleted file mode 100644
index 36543c531..000000000
--- a/libtransport/src/test/fec_reed_solomon.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gtest/gtest.h>
-#include <hicn/transport/interfaces/socket_consumer.h>
-#include <hicn/transport/interfaces/socket_options_keys.h>
-#include <hicn/transport/interfaces/socket_producer.h>
-#include <hicn/transport/interfaces/global_conf_interface.h>
-
-#include <asio/io_service.hpp>
-#include <asio/steady_timer.hpp>
-#include <fec/rs.h>
-
-namespace transport {
-namespace interface {
-
-namespace {
-
-class ConsumerProducerTest : public ::testing::Test,
- public ConsumerSocket::ReadCallback {
- static const constexpr char prefix[] = "b001::1/128";
- static const constexpr char name[] = "b001::1";
- static const constexpr double prod_rate = 1.0e6;
- static const constexpr size_t payload_size = 1200;
- static constexpr std::size_t receive_buffer_size = 1500;
- static const constexpr double prod_interval_microseconds =
- double(payload_size) * 8 * 1e6 / prod_rate;
-
- public:
- ConsumerProducerTest()
- : io_service_(),
- rtc_timer_(io_service_),
- consumer_(TransportProtocolAlgorithms::RTC, io_service_),
- producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_),
- producer_prefix_(prefix),
- consumer_name_(name),
- packets_sent_(0),
- packets_received_(0) {
- global_config::IoModuleConfiguration config;
- config.name = "loopback_module";
- config.set();
- }
-
- virtual ~ConsumerProducerTest() {
- // You can do clean-up work that doesn't throw exceptions here.
- }
-
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
-
- virtual void SetUp() override {
- // Code here will be called immediately after the constructor (right
- // before each test).
-
- auto ret = consumer_.setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, this);
- ASSERT_EQ(ret, SOCKET_OPTION_SET);
-
- consumer_.connect();
- producer_.registerPrefix(producer_prefix_);
- producer_.connect();
- }
-
- virtual void TearDown() override {
- // Code here will be called immediately after each test (right
- // before the destructor).
- }
-
- void setTimer() {
- using namespace std::chrono;
- rtc_timer_.expires_from_now(
- microseconds(unsigned(prod_interval_microseconds)));
- rtc_timer_.async_wait(std::bind(&ConsumerProducerTest::produceRTCPacket,
- this, std::placeholders::_1));
- }
-
- void produceRTCPacket(const std::error_code &ec) {
- if (ec) {
- FAIL() << "Failed to schedule packet production";
- io_service_.stop();
- }
-
- producer_.produceDatagram(consumer_name_, payload_, payload_size);
- packets_sent_++;
- setTimer();
- }
-
- // Consumer callback
- bool isBufferMovable() noexcept override { return false; }
-
- void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override {
- *application_buffer = receive_buffer_;
- *max_length = receive_buffer_size;
- }
-
- void readDataAvailable(std::size_t length) noexcept override {}
-
- size_t maxBufferSize() const override { return receive_buffer_size; }
-
- void readError(const std::error_code ec) noexcept override {
- FAIL() << "Error while reading from RTC socket";
- io_service_.stop();
- }
-
- void readSuccess(std::size_t total_size) noexcept override {
- packets_received_++;
- }
-
- asio::io_service io_service_;
- asio::steady_timer rtc_timer_;
- ConsumerSocket consumer_;
- ProducerSocket producer_;
- core::Prefix producer_prefix_;
- core::Name consumer_name_;
- uint8_t payload_[payload_size];
- uint8_t receive_buffer_[payload_size];
-
- uint64_t packets_sent_;
- uint64_t packets_received_;
-};
-
-const char ConsumerProducerTest::prefix[];
-const char ConsumerProducerTest::name[];
-
-} // namespace
-
-TEST_F(ConsumerProducerTest, EndToEnd) {
- produceRTCPacket(std::error_code());
- consumer_.consume(consumer_name_);
-
- io_service_.run();
-}
-
-} // namespace interface
-
-} // namespace transport
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-} \ No newline at end of file
diff --git a/libtransport/src/test/fec_rely.cc b/libtransport/src/test/fec_rely.cc
deleted file mode 100644
index e7745bae5..000000000
--- a/libtransport/src/test/fec_rely.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gtest/gtest.h>
-#include <hicn/transport/interfaces/socket_consumer.h>
-#include <hicn/transport/interfaces/socket_options_keys.h>
-#include <hicn/transport/interfaces/socket_producer.h>
-#include <hicn/transport/interfaces/global_conf_interface.h>
-
-#include <asio/io_service.hpp>
-#include <asio/steady_timer.hpp>
-
-#include <rely/encoder.hpp>
-#include <rely/decoder.hpp>
-
-namespace transport {
-namespace interface {
-
-namespace {
-
-class ConsumerProducerTest : public ::testing::Test,
- public ConsumerSocket::ReadCallback {
- static const constexpr char prefix[] = "b001::1/128";
- static const constexpr char name[] = "b001::1";
- static const constexpr double prod_rate = 1.0e6;
- static const constexpr size_t payload_size = 1200;
- static constexpr std::size_t receive_buffer_size = 1500;
- static const constexpr double prod_interval_microseconds =
- double(payload_size) * 8 * 1e6 / prod_rate;
-
- public:
- ConsumerProducerTest()
- : io_service_(),
- rtc_timer_(io_service_),
- consumer_(TransportProtocolAlgorithms::RTC, io_service_),
- producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_),
- producer_prefix_(prefix),
- consumer_name_(name),
- packets_sent_(0),
- packets_received_(0) {
- global_config::IoModuleConfiguration config;
- config.name = "loopback_module";
- config.set();
- }
-
- virtual ~ConsumerProducerTest() {
- // You can do clean-up work that doesn't throw exceptions here.
- }
-
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
-
- virtual void SetUp() override {
- // Code here will be called immediately after the constructor (right
- // before each test).
-
- auto ret = consumer_.setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, this);
- ASSERT_EQ(ret, SOCKET_OPTION_SET);
-
- consumer_.connect();
- producer_.registerPrefix(producer_prefix_);
- producer_.connect();
- }
-
- virtual void TearDown() override {
- // Code here will be called immediately after each test (right
- // before the destructor).
- }
-
- void setTimer() {
- using namespace std::chrono;
- rtc_timer_.expires_from_now(
- microseconds(unsigned(prod_interval_microseconds)));
- rtc_timer_.async_wait(std::bind(&ConsumerProducerTest::produceRTCPacket,
- this, std::placeholders::_1));
- }
-
- void produceRTCPacket(const std::error_code &ec) {
- if (ec) {
- FAIL() << "Failed to schedule packet production";
- io_service_.stop();
- }
-
- producer_.produceDatagram(consumer_name_, payload_, payload_size);
- packets_sent_++;
- setTimer();
- }
-
- // Consumer callback
- bool isBufferMovable() noexcept override { return false; }
-
- void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override {
- *application_buffer = receive_buffer_;
- *max_length = receive_buffer_size;
- }
-
- void readDataAvailable(std::size_t length) noexcept override {}
-
- size_t maxBufferSize() const override { return receive_buffer_size; }
-
- void readError(const std::error_code ec) noexcept override {
- FAIL() << "Error while reading from RTC socket";
- io_service_.stop();
- }
-
- void readSuccess(std::size_t total_size) noexcept override {
- packets_received_++;
- }
-
- asio::io_service io_service_;
- asio::steady_timer rtc_timer_;
- ConsumerSocket consumer_;
- ProducerSocket producer_;
- core::Prefix producer_prefix_;
- core::Name consumer_name_;
- uint8_t payload_[payload_size];
- uint8_t receive_buffer_[payload_size];
-
- uint64_t packets_sent_;
- uint64_t packets_received_;
-};
-
-const char ConsumerProducerTest::prefix[];
-const char ConsumerProducerTest::name[];
-
-} // namespace
-
-TEST_F(ConsumerProducerTest, EndToEnd) {
- produceRTCPacket(std::error_code());
- consumer_.consume(consumer_name_);
-
- io_service_.run();
-}
-
-} // namespace interface
-
-} // namespace transport
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-} \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/security/key_id.h b/libtransport/src/test/main.cc
index d67b73d7a..a4d7ce1b3 100644
--- a/libtransport/includes/hicn/transport/security/key_id.h
+++ b/libtransport/src/test/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -13,13 +13,10 @@
* limitations under the License.
*/
-#pragma once
+#include <gtest/gtest.h>
-#include <cstdint>
-#include <utility>
-
-namespace utils {
-
-using KeyId = std::pair<uint8_t*, uint8_t>;
-
-}
+int main(int argc, char **argv) {
+ srand(time(0));
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+} \ No newline at end of file
diff --git a/libtransport/src/test/test_auth.cc b/libtransport/src/test/test_auth.cc
index 976981cce..db1c3b52f 100644
--- a/libtransport/src/test/test_auth.cc
+++ b/libtransport/src/test/test_auth.cc
@@ -14,7 +14,7 @@
*/
#include <gtest/gtest.h>
-#include <hicn/transport/auth/crypto_hash_type.h>
+#include <hicn/transport/auth/crypto_hash.h>
#include <hicn/transport/auth/identity.h>
#include <hicn/transport/auth/signer.h>
#include <hicn/transport/auth/verifier.h>
@@ -45,14 +45,15 @@ TEST_F(AuthTest, VoidVerifier) {
// Verify that VoidVerifier validates the packet
std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>();
- ASSERT_EQ(verifier->verifyPacket(&packet), true);
- ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+ EXPECT_EQ(verifier->verifyPacket(&packet), true);
+ EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
}
-TEST_F(AuthTest, RSAVerifier) {
+TEST_F(AuthTest, AsymmetricRSA) {
// Create the RSA signer from an Identity object
Identity identity("test_rsa.p12", PASSPHRASE, CryptoSuite::RSA_SHA256, 1024u,
30, "RSAVerifier");
+
std::shared_ptr<Signer> signer = identity.getSigner();
// Create a content object
@@ -66,21 +67,125 @@ TEST_F(AuthTest, RSAVerifier) {
signer->signPacket(&packet);
// Create the RSA verifier
- PARCKey *key = parcSigner_CreatePublicKey(signer->getParcSigner());
std::shared_ptr<Verifier> verifier =
- std::make_shared<AsymmetricVerifier>(key);
+ std::make_shared<AsymmetricVerifier>(identity.getCertificate());
+
+ EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
+ EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256);
+ EXPECT_EQ(signer->getSuite(), CryptoSuite::RSA_SHA256);
+ EXPECT_EQ(signer->getSignatureSize(), 128u);
+ EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+}
+
+TEST_F(AuthTest, AsymmetricBufferRSA) {
+ // Create the RSA signer from an Identity object
+ Identity identity("test_rsa.p12", PASSPHRASE, CryptoSuite::RSA_SHA256, 1024u,
+ 30, "RSAVerifier");
+
+ std::shared_ptr<AsymmetricSigner> signer = identity.getSigner();
+ std::string payload = "bonjour";
- ASSERT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
- ASSERT_EQ(signer->getCryptoHashType(), CryptoHashType::SHA_256);
- ASSERT_EQ(signer->getCryptoSuite(), CryptoSuite::RSA_SHA256);
- ASSERT_EQ(signer->getSignatureSize(), 128u);
- ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+ std::vector<uint8_t> buffer(payload.begin(), payload.end());
+ signer->signBuffer(buffer);
+ std::vector<uint8_t> sig = signer->getSignature();
- // Release PARC objects
- parcKey_Release(&key);
+ std::shared_ptr<X509> cert = identity.getCertificate();
+ AsymmetricVerifier verif(cert);
+ bool res = verif.verifyBuffer(
+ buffer, std::vector<uint8_t>(sig.data(), sig.data() + sig.size()),
+ CryptoHashType::SHA256);
+ EXPECT_EQ(res, true);
}
-TEST_F(AuthTest, HMACVerifier) {
+TEST_F(AuthTest, AsymmetricBufferDSA) {
+ // Create the DSA signer from an Identity object
+ Identity identity("test_dsa.p12", PASSPHRASE, CryptoSuite::DSA_SHA256, 1024u,
+ 30, "DSAVerifier");
+
+ std::shared_ptr<AsymmetricSigner> signer = identity.getSigner();
+ std::string payload = "bonjour";
+
+ std::vector<uint8_t> buffer(payload.begin(), payload.end());
+ signer->signBuffer(buffer);
+ std::vector<uint8_t> sig = signer->getSignature();
+
+ std::shared_ptr<X509> cert = identity.getCertificate();
+ AsymmetricVerifier verif(cert);
+ bool res = verif.verifyBuffer(
+ buffer, std::vector<uint8_t>(sig.data(), sig.data() + sig.size()),
+ CryptoHashType::SHA256);
+ EXPECT_EQ(res, true);
+}
+
+TEST_F(AuthTest, AsymmetricVerifierDSA) {
+ // Create the DSA signer from an Identity object
+ Identity identity("test_dsa.p12", PASSPHRASE, CryptoSuite::DSA_SHA256, 1024u,
+ 30, "DSAVerifier");
+
+ std::shared_ptr<Signer> signer = identity.getSigner();
+
+ // Create a content object
+ core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
+
+ // Fill it with bogus data
+ uint8_t buffer[256] = {0};
+ packet.appendPayload(buffer, 256);
+ // this test has to be done before the signature is compute
+ // EXPECT_EQ(signer->getSignatureSize(), 256u);
+ signer->signPacket(&packet);
+ std::shared_ptr<Verifier> verifier =
+ std::make_shared<AsymmetricVerifier>(identity.getCertificate());
+
+ EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
+ EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256);
+ EXPECT_EQ(signer->getSuite(), CryptoSuite::DSA_SHA256);
+ EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+}
+
+TEST_F(AuthTest, AsymmetricBufferECDSA) {
+ // Create the ECDSA signer from an Identity object
+ Identity identity("test_ecdsa.p12", PASSPHRASE, CryptoSuite::ECDSA_SHA256,
+ 256u, 30, "ECDSAVerifier");
+
+ std::shared_ptr<AsymmetricSigner> signer = identity.getSigner();
+ std::string payload = "bonjour";
+
+ std::vector<uint8_t> buffer(payload.begin(), payload.end());
+ signer->signBuffer(buffer);
+ std::vector<uint8_t> sig = signer->getSignature();
+
+ std::shared_ptr<X509> cert = identity.getCertificate();
+ AsymmetricVerifier verif(cert);
+ bool res = verif.verifyBuffer(
+ buffer, std::vector<uint8_t>(sig.data(), sig.data() + sig.size()),
+ CryptoHashType::SHA256);
+ EXPECT_EQ(res, true);
+}
+
+TEST_F(AuthTest, AsymmetricVerifierECDSA) {
+ Identity identity("test_ecdsa.p12", PASSPHRASE, CryptoSuite::ECDSA_SHA256,
+ 256u, 30, "ECDSAVerifier");
+
+ std::shared_ptr<Signer> signer = identity.getSigner();
+ std::shared_ptr<Verifier> verifier =
+ std::make_shared<AsymmetricVerifier>(identity.getCertificate());
+ // Create a content object
+ for (int i = 0; i < 100; i++) {
+ core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
+
+ // Fill it with bogus data
+ uint8_t buffer[256] = {0};
+ packet.appendPayload(buffer, 256);
+ signer->signPacket(&packet);
+
+ EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
+ EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256);
+ EXPECT_EQ(signer->getSuite(), CryptoSuite::ECDSA_SHA256);
+ EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+ }
+}
+
+TEST_F(AuthTest, HMACbuffer) {
// Create the HMAC signer from a passphrase
std::shared_ptr<Signer> signer =
std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, PASSPHRASE);
@@ -88,6 +193,25 @@ TEST_F(AuthTest, HMACVerifier) {
// Create a content object
core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
+ std::string payload = "bonjour";
+ std::vector<uint8_t> buffer(payload.begin(), payload.end());
+ signer->signBuffer(buffer);
+ std::vector<uint8_t> sig = signer->getSignature();
+ SymmetricVerifier hmac(PASSPHRASE);
+ bool res = hmac.verifyBuffer(
+ buffer, std::vector<uint8_t>(sig.data(), sig.data() + sig.size()),
+ CryptoHashType::SHA256);
+ EXPECT_EQ(res, true);
+}
+
+TEST_F(AuthTest, HMACVerifier) {
+ // Create the HMAC signer from a passphrase
+ std::shared_ptr<SymmetricSigner> signer =
+ std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, PASSPHRASE);
+
+ // Create a content object
+ core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
+
// Fill it with bogus data
uint8_t buffer[256] = {0};
packet.appendPayload(buffer, 256);
@@ -99,11 +223,11 @@ TEST_F(AuthTest, HMACVerifier) {
std::shared_ptr<Verifier> verifier =
std::make_shared<SymmetricVerifier>(PASSPHRASE);
- ASSERT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
- ASSERT_EQ(signer->getCryptoHashType(), CryptoHashType::SHA_256);
- ASSERT_EQ(signer->getCryptoSuite(), CryptoSuite::HMAC_SHA256);
- ASSERT_EQ(signer->getSignatureSize(), 32u);
- ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+ EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
+ EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256);
+ EXPECT_EQ(signer->getSuite(), CryptoSuite::HMAC_SHA256);
+ EXPECT_EQ(signer->getSignatureSize(), 32u);
+ EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
}
} // namespace auth
diff --git a/libtransport/src/test/test_consumer_producer_rtc.cc b/libtransport/src/test/test_consumer_producer_rtc.cc
index 87385971a..8541a9e1a 100644
--- a/libtransport/src/test/test_consumer_producer_rtc.cc
+++ b/libtransport/src/test/test_consumer_producer_rtc.cc
@@ -14,14 +14,12 @@
*/
#include <gtest/gtest.h>
+#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/interfaces/global_conf_interface.h>
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
#include <hicn/transport/interfaces/socket_producer.h>
-#include <asio/io_service.hpp>
-#include <asio/steady_timer.hpp>
-
namespace transport {
namespace interface {
@@ -151,7 +149,7 @@ const char ConsumerProducerTest::name[];
} // namespace
-TEST_F(ConsumerProducerTest, EndToEnd) {
+TEST_F(ConsumerProducerTest, DISABLED_EndToEnd) {
produceRTCPacket(std::error_code());
consumer_.consume(consumer_name_);
setStopTimer();
@@ -165,12 +163,3 @@ TEST_F(ConsumerProducerTest, EndToEnd) {
} // namespace interface
} // namespace transport
-
-int main(int argc, char **argv) {
-#if 0
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-#else
- return 0;
-#endif
-} \ No newline at end of file
diff --git a/libtransport/src/test/test_core_manifest.cc b/libtransport/src/test/test_core_manifest.cc
index f98147d43..93f4e87cb 100644
--- a/libtransport/src/test/test_core_manifest.cc
+++ b/libtransport/src/test/test_core_manifest.cc
@@ -16,7 +16,7 @@
#include <core/manifest_format_fixed.h>
#include <core/manifest_inline.h>
#include <gtest/gtest.h>
-#include <hicn/transport/auth/crypto_hash_type.h>
+#include <hicn/transport/auth/crypto_hash.h>
#include <test/packet_samples.h>
#include <climits>
@@ -124,9 +124,9 @@ TEST_F(ManifestTest, SetManifestType) {
TEST_F(ManifestTest, SetHashAlgorithm) {
manifest1_.clear();
- auth::CryptoHashType hash1 = auth::CryptoHashType::SHA_512;
- auth::CryptoHashType hash2 = auth::CryptoHashType::CRC32C;
- auth::CryptoHashType hash3 = auth::CryptoHashType::SHA_256;
+ auth::CryptoHashType hash1 = auth::CryptoHashType::SHA512;
+ auth::CryptoHashType hash2 = auth::CryptoHashType::BLAKE2B512;
+ auth::CryptoHashType hash3 = auth::CryptoHashType::SHA256;
manifest1_.setHashAlgorithm(hash1);
auto type_returned1 = manifest1_.getHashAlgorithm();
@@ -191,9 +191,9 @@ TEST_F(ManifestTest, SetSuffixList) {
data[i].resize(32);
std::generate(std::begin(data[i]), std::end(data[i]), std::ref(rbe));
suffixes[i] = idis(eng);
- entries[i] = std::make_pair(
- suffixes[i], auth::CryptoHash(data[i].data(), data[i].size(),
- auth::CryptoHashType::SHA_256));
+ entries[i] = std::make_pair(suffixes[i],
+ auth::CryptoHash(data[i].data(), data[i].size(),
+ auth::CryptoHashType::SHA256));
manifest1_.addSuffixHash(entries[i].first, entries[i].second);
}
@@ -223,8 +223,3 @@ TEST_F(ManifestTest, SetSuffixList) {
} // namespace core
} // namespace transport
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/libtransport/src/test/test_event_thread.cc b/libtransport/src/test/test_event_thread.cc
index e66b49f10..549ff9c1a 100644
--- a/libtransport/src/test/test_event_thread.cc
+++ b/libtransport/src/test/test_event_thread.cc
@@ -71,7 +71,7 @@ double stdDeviation(const unsigned long samples[], int size) {
} // namespace
-TEST_F(EventThreadTest, SchedulingDelay) {
+TEST_F(EventThreadTest, DISABLED_SchedulingDelay) {
using namespace std::chrono;
const size_t size = 1000000;
std::vector<unsigned long> samples(size);
@@ -95,12 +95,3 @@ TEST_F(EventThreadTest, SchedulingDelay) {
}
} // namespace utils
-
-int main(int argc, char **argv) {
-#if 0
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-#else
- return 0;
-#endif
-} \ No newline at end of file
diff --git a/libtransport/src/test/test_fec_reedsolomon.cc b/libtransport/src/test/test_fec_reedsolomon.cc
index 3b10b7307..c7e10d111 100644
--- a/libtransport/src/test/test_fec_reedsolomon.cc
+++ b/libtransport/src/test/test_fec_reedsolomon.cc
@@ -14,21 +14,21 @@
* limitations under the License.
*/
-#include <core/rs.h>
#include <gtest/gtest.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/global_object_pool.h>
+#include <protocols/fec/rs.h>
#include <algorithm>
#include <iostream>
#include <random>
namespace transport {
-namespace core {
+namespace protocol {
-double ReedSolomonTest(int k, int n, int size) {
- fec::encoder encoder(k, n);
- fec::decoder decoder(k, n);
+double ReedSolomonTest(int k, int n, int seq_offset, int size) {
+ fec::RSEncoder encoder(k, n, seq_offset);
+ fec::RSDecoder decoder(k, n, seq_offset);
std::vector<fec::buffer> tx_block(k);
std::vector<fec::buffer> rx_block(k);
@@ -36,27 +36,31 @@ double ReedSolomonTest(int k, int n, int size) {
int run = 0;
int iterations = 100;
- auto &packet_manager = PacketManager<>::getInstance();
-
- encoder.setFECCallback([&tx_block](std::vector<fec::buffer> &repair_packets) {
- for (auto &p : repair_packets) {
- // Append repair symbols to tx_block
- tx_block.emplace_back(std::move(p));
- }
- });
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ encoder.setFECCallback(
+ [&tx_block](
+ std::vector<std::pair<uint32_t, fec::buffer>> &repair_packets) {
+ for (auto &p : repair_packets) {
+ // Append repair symbols to tx_block
+ tx_block.emplace_back(std::move(p).second);
+ }
+ });
- decoder.setFECCallback([&](std::vector<fec::buffer> &source_packets) {
- for (int i = 0; i < k; i++) {
- // Compare decoded source packets with original transmitted packets.
- if (*tx_block[i] != *source_packets[i]) {
- count++;
- }
- }
- });
+ decoder.setFECCallback(
+ [&](std::vector<std::pair<uint32_t, fec::buffer>> &source_packets) {
+ for (int i = 0; i < k; i++) {
+ // Compare decoded source packets with original transmitted packets.
+ if (*tx_block[i] != *source_packets[i].second) {
+ count++;
+ }
+ }
+ });
do {
// Discard eventual packet appended in previous callback call
tx_block.erase(tx_block.begin() + k, tx_block.end());
+ auto _seq_offet = seq_offset;
// Initialization. Feed encoder with first k source packets
for (int i = 0; i < k; i++) {
@@ -74,8 +78,8 @@ double ReedSolomonTest(int k, int n, int size) {
std::generate(packet->writableData(), packet->writableTail(), rand);
std::fill(packet->writableData(), packet->writableTail(), i + 1);
- // Set first byte of payload to i, to reorder at receiver side
- packet->writableData()[0] = uint8_t(i);
+ // Set first byte of payload to seq_offset, to reorder at receiver side
+ packet->writableData()[0] = uint8_t(_seq_offet++);
// Store packet in tx buffer and clear rx buffer
tx_block[i] = std::move(packet);
@@ -99,10 +103,11 @@ double ReedSolomonTest(int k, int n, int size) {
rx_block[rxi++] = tx_block[i];
if (i < k) {
// Source packet
- decoder.consume(rx_block[rxi - 1], rx_block[rxi - 1]->data()[0]);
+ decoder.consumeSource(rx_block[rxi - 1],
+ rx_block[rxi - 1]->data()[0]);
} else {
// Repair packet
- decoder.consume(rx_block[rxi - 1]);
+ decoder.consumeRepair(rx_block[rxi - 1]);
}
}
@@ -118,10 +123,10 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
int n = 24;
int size = 1000;
- fec::encoder encoder(k, n);
- fec::decoder decoder(k, n);
+ fec::RSEncoder encoder(k, n);
+ fec::RSDecoder decoder(k, n);
- auto &packet_manager = PacketManager<>::getInstance();
+ auto &packet_manager = core::PacketManager<>::getInstance();
std::vector<std::pair<fec::buffer, uint32_t>> tx_block;
std::vector<std::pair<fec::buffer, uint32_t>> rx_block;
@@ -133,28 +138,31 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
int tx_packets = k * n_sourceblocks;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
- encoder.setFECCallback([&](std::vector<fec::buffer> &repair_packets) {
- for (auto &p : repair_packets) {
- // Append repair symbols to tx_block
- tx_block.emplace_back(std::move(p), ++i);
- }
+ encoder.setFECCallback(
+ [&](std::vector<std::pair<uint32_t, fec::buffer>> &repair_packets) {
+ for (auto &p : repair_packets) {
+ // Append repair symbols to tx_block
+ tx_block.emplace_back(std::move(p.second), ++i);
+ }
- EXPECT_EQ(tx_block.size(), size_t(n));
+ EXPECT_EQ(tx_block.size(), size_t(n));
- // Select k packets to send, including at least one symbol. We start from
- // the end for this reason.
- for (int j = n - 1; j > n - k - 1; j--) {
- rx_block.emplace_back(std::move(tx_block[j]));
- }
+ // Select k packets to send, including at least one symbol. We start
+ // from the end for this reason.
+ for (int j = n - 1; j > n - k - 1; j--) {
+ rx_block.emplace_back(std::move(tx_block[j]));
+ }
- // Clear tx block for next source block
- tx_block.clear();
- encoder.clear();
- });
+ // Clear tx block for next source block
+ tx_block.clear();
+ encoder.clear();
+ });
// The decode callback must be called exactly n_sourceblocks times
decoder.setFECCallback(
- [&](std::vector<fec::buffer> &source_packets) { count++; });
+ [&](std::vector<std::pair<uint32_t, fec::buffer>> &source_packets) {
+ count++;
+ });
// Produce n * n_sourceblocks
// - ( k ) * n_sourceblocks source packets
@@ -194,10 +202,10 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
int index = p.second % n;
if (index < k) {
// Source packet
- decoder.consume(p.first, p.second);
+ decoder.consumeSource(p.first, p.second);
} else {
// Repair packet
- decoder.consume(p.first);
+ decoder.consumeRepair(p.first);
}
}
@@ -205,66 +213,22 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) {
EXPECT_EQ(count, n_sourceblocks);
}
-TEST(ReedSolomonTest, RSk1n3) {
- int k = 1;
- int n = 3;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonTest, RSk6n10) {
- int k = 6;
- int n = 10;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonTest, RSk8n32) {
- int k = 8;
- int n = 32;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonTest, RSk16n24) {
- int k = 16;
- int n = 24;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonTest, RSk10n30) {
- int k = 10;
- int n = 30;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonTest, RSk10n40) {
- int k = 10;
- int n = 40;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonTest, RSk10n60) {
- int k = 10;
- int n = 60;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonTest, RSk10n90) {
- int k = 10;
- int n = 90;
- int size = 1000;
- EXPECT_LE(ReedSolomonTest(k, n, size), 0);
-}
-
-TEST(ReedSolomonMultiBlockTest, RSMB1) {
- int blocks = 1;
- ReedSolomonMultiBlockTest(blocks);
-}
+/**
+ * @brief Use foreach_rs_fec_type to automatically generate the code of the
+ * tests and avoid copy/paste the same function.
+ */
+#define _(name, k, n) \
+ TEST(ReedSolomonTest, RSK##k##N##n) { \
+ int K = k; \
+ int N = n; \
+ int seq_offset = 0; \
+ int size = 1000; \
+ EXPECT_LE(ReedSolomonTest(K, N, seq_offset, size), 0); \
+ seq_offset = 12345; \
+ EXPECT_LE(ReedSolomonTest(K, N, seq_offset, size), 0); \
+ }
+foreach_rs_fec_type
+#undef _
TEST(ReedSolomonMultiBlockTest, RSMB10) {
int blocks = 10;
@@ -281,11 +245,5 @@ TEST(ReedSolomonMultiBlockTest, RSMB1000) {
ReedSolomonMultiBlockTest(blocks);
}
-int main(int argc, char **argv) {
- srand(time(0));
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-
-} // namespace core
+} // namespace protocol
} // namespace transport
diff --git a/libtransport/src/test/test_fec_rely_wrapper.cc b/libtransport/src/test/test_fec_rely_wrapper.cc
new file mode 100644
index 000000000..c5b73f8d2
--- /dev/null
+++ b/libtransport/src/test/test_fec_rely_wrapper.cc
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/utils/log.h>
+#include <protocols/fec/rely.h>
+
+#include <queue>
+
+namespace transport {
+namespace protocol {
+
+std::string printMissing(
+ const std::map<uint32_t, core::ContentObject::Ptr> &missing) {
+ std::stringstream stream;
+
+ for (auto &[seq, packet] : missing) {
+ stream << " " << seq;
+ }
+
+ stream << "\n";
+
+ return stream.str();
+}
+
+/**
+ * @brief Test encode-decode operations performed using the wrapper for rely
+ *
+ * @param k Number of source symbols
+ * @param n Sum of source symbols and repair symbols
+ * @param max_packet_size The max packet size the decoder will expect.
+ * @param timeout The timeout used by rely
+ * https://rely.steinwurf.com/docs/6.1.0/design/timeout_configuration.html
+ * @param max_iterations The number of packets to send
+ * @param loss_rate The loss rate
+ */
+void testRelyEncoderDecoder(uint32_t k, uint32_t n, size_t max_packet_size,
+ int64_t timeout, uint32_t max_iterations,
+ int loss_rate) {
+ // Create 1 encoder and 1 decoder
+ fec::RelyEncoder _encoder(k, n);
+ fec::RelyDecoder _decoder(k, n);
+
+ // Seed the pseudo-random with known value to always get same loss pattern
+ srand(k * n);
+
+ // We will interact with rely encoder/decoder using the interface
+ fec::ProducerFEC &encoder = _encoder;
+ fec::ConsumerFEC &decoder = _decoder;
+
+ // Initialize current iteration
+ uint32_t iterations = 0;
+
+ // Packet allocator
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ // Store packets to verify them in the decoder callback
+ std::map<uint32_t, core::ContentObject::Ptr> saved_packets;
+
+ // Save repair packets here in encoder callback
+ std::queue<fec::buffer> pending_repair_packets;
+
+ // Set callback called by encoder when a buffer is required.
+ encoder.setBufferCallback([](std::size_t size) -> fec::buffer {
+ auto ret =
+ core::PacketManager<>::getInstance().getPacket<core::ContentObject>();
+ ret->updateLength(size);
+ ret->append(size);
+ ret->trimStart(ret->headerSize());
+ assert(ret->length() >= size);
+
+ return ret;
+ });
+
+ // Set callback to be called by encoder when repair packets are ready
+ encoder.setFECCallback(
+ [&](std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
+ // We must get n - k symbols
+ EXPECT_EQ(packets.size(), n - k);
+ // TRANSPORT_LOGD("Got %zu symbols", packets.size());
+
+ // Save symbols in pending_repair_packets queue and increment iterations
+ for (auto &packet : packets) {
+ ++iterations;
+ pending_repair_packets.push(packet.second);
+ }
+ });
+
+ // Set callback to be called when decoder recover a packet
+ decoder.setFECCallback(
+ [&](std::vector<std::pair<uint32_t, fec::buffer>> &packets) {
+ for (auto &packet : packets) {
+ // TRANSPORT_LOGD("Recovering packet %u", packet.first);
+
+ // Ensure recovered packet is in packets actually produced by encoder
+ auto original = saved_packets.find(packet.first);
+ ASSERT_TRUE(original != saved_packets.end());
+ auto &original_packet = *original->second;
+
+ // Remove additional headers at the beginning of the packet. This may
+ // change in the future.
+ original_packet.trimStart(60 /* Ip + TCP */ + 28 /* Rely header */ +
+ 4 /* Packet size */);
+
+ // Recovered packet should be equal to the original one
+ EXPECT_TRUE(original_packet == *packet.second);
+
+ // Restore removed headers
+ original_packet.prepend(60 + 28 + 4);
+
+ // Erase packet from saved packet list
+ saved_packets.erase(original);
+ }
+ });
+
+ // Send max_iterations packets from encoder to decoder
+ while (iterations < max_iterations) {
+ // Create a payload, the size is between 50 and 1350 bytes.
+ auto payload_size = 50 + (rand() % 1300);
+ uint8_t payload[max_packet_size];
+ std::generate(payload, payload + payload_size, rand);
+
+ // Get a packet from global pool and set name
+ auto buffer = packet_manager.getPacket<core::ContentObject>();
+ buffer->setName(core::Name("b001::abcd", iterations));
+
+ // Get offset
+ auto offset = buffer->headerSize();
+
+ // Copy payload into packet. We keep the payload to compare returned packet
+ // with original one (since rely encoder does modify the packet by adding
+ // its own header).
+ buffer->appendPayload(payload, payload_size);
+
+ // Save packet in the saving_packets list
+ // TRANSPORT_LOGD("Saving packet with index %lu", iterations);
+ saved_packets.emplace(iterations, buffer);
+
+ // Feed buffer into the encoder. This will eventually trigger a call to the
+ // FEC callback as soon as k packets are fed into the endocer.
+ encoder.onPacketProduced(*buffer, offset);
+
+ // Check returned packet. We calculate the difference in size and we compare
+ // only the part of the returned packet corresponding to the original
+ // payload. Rely should only add a header and should not modify the actual
+ // payload content. If it does it, this check will fail.
+ auto diff = buffer->length() - payload_size - offset;
+ // TRANSPORT_LOGD("Difference is %zu", diff);
+ auto cmp =
+ std::memcmp(buffer->data() + offset + diff, payload, payload_size);
+ EXPECT_FALSE(cmp);
+
+ // Drop condition. Id addition to the loss rate, we ensure that no drops are
+ // perfomed in the last 10% of the total iterations. This is done because
+ // rely uses a sliding-window mechanism to recover, and if we suddenly stop
+ // we may not be able to recover missing packets that would be recovered
+ // using future packets that are not created in the test. For this reason,
+ // we ensure the test ends without losses.
+#define DROP_CONDITION(loss_rate, max_iterations) \
+ (rand() % 100) >= loss_rate || iterations >= max_iterations * 0.9
+
+ // Handle the source packet to the decoder, id drop condition returns true
+ if (DROP_CONDITION(loss_rate, max_iterations)) {
+ // Pass packet to decoder
+ // TRANSPORT_LOGD("Passing packet %u to decoder",
+ // buffer->getName().getSuffix());
+ decoder.onDataPacket(*buffer, offset);
+ } else {
+ // TRANSPORT_LOGD("Packet %u, dropped", buffer->getName().getSuffix());
+ }
+
+ // Check if previous call to encoder.consumer() generated repair packets,
+ // and if yes, feed them to the decoder.
+ while (pending_repair_packets.size()) {
+ // Also repair packets can be lost
+ if (DROP_CONDITION(loss_rate, max_iterations)) {
+ auto &packet = pending_repair_packets.front();
+ // TRANSPORT_LOGD("Passing packet %u to decoder", iterations);
+ core::ContentObject &co = (core::ContentObject &)(*packet);
+ decoder.onDataPacket(co, 0);
+ } else {
+ // TRANSPORT_LOGD("Packet (repair) %u dropped", iterations);
+ }
+
+ // Remove packet from the queue
+ pending_repair_packets.pop();
+ }
+
+ ++iterations;
+ }
+
+ // We expect this test to terminate with a full recover of all the packets and
+ // 0.001 residual losses
+ EXPECT_LE(saved_packets.size(), iterations * 0.001)
+ << printMissing(saved_packets);
+
+ // Reset seed
+ srand(time(0));
+}
+
+/**
+ * @brief Use foreach_rely_fec_type to automatically generate the code of the
+ * tests and avoid copy/paste the same function.
+ */
+#define _(name, k, n) \
+ TEST(RelyTest, RelyK##k##N##n) { \
+ int K = k; \
+ int N = n; \
+ uint32_t max_iterations = 1000; \
+ int size = 1400; \
+ int64_t timeout = 120; \
+ int loss_rate = 10; \
+ testRelyEncoderDecoder(K, N, size, timeout, max_iterations, loss_rate); \
+ }
+foreach_rely_fec_type
+#undef _
+
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/test/test_indexer.cc b/libtransport/src/test/test_indexer.cc
new file mode 100644
index 000000000..9c12e2037
--- /dev/null
+++ b/libtransport/src/test/test_indexer.cc
@@ -0,0 +1,322 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <protocols/incremental_indexer_bytestream.h>
+#include <protocols/indexer.h>
+#include <protocols/rtc/rtc_indexer.h>
+
+#include <algorithm>
+#include <iostream>
+#include <random>
+
+namespace transport {
+namespace protocol {
+
+class IncrementalIndexerTest : public ::testing::Test {
+ protected:
+ IncrementalIndexerTest() : indexer_(nullptr, nullptr) {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~IncrementalIndexerTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ IncrementalIndexer indexer_;
+};
+
+class RtcIndexerTest : public ::testing::Test {
+ protected:
+ RtcIndexerTest() : indexer_(nullptr, nullptr) {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~RtcIndexerTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ indexer_.setFirstSuffix(0);
+ indexer_.reset();
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ static const constexpr uint32_t LIMIT = (1 << 31);
+ rtc::RtcIndexer<LIMIT> indexer_;
+};
+
+void testIncrement(Indexer &indexer) {
+ // As a first index we should get zero
+ auto index = indexer.getNextSuffix();
+ EXPECT_EQ(index, uint32_t(0));
+
+ // Check if the sequence works for consecutive incremental numbers
+ for (uint32_t i = 1; i < 4096; i++) {
+ index = indexer.getNextSuffix();
+ EXPECT_EQ(index, i);
+ }
+
+ index = indexer.getNextSuffix();
+ EXPECT_NE(index, uint32_t(0));
+}
+
+void testJump(Indexer &indexer) {
+ // Fist suffix is 0
+ auto index = indexer.getNextSuffix();
+ EXPECT_EQ(index, uint32_t(0));
+
+ // Next suffix should be 1, but we jump to 12345
+ uint32_t jump = 12345;
+ indexer.jumpToIndex(jump);
+
+ // This takes place immediately
+ index = indexer.getNextSuffix();
+ EXPECT_EQ(index, jump);
+}
+
+TEST_F(IncrementalIndexerTest, TestReset) {
+ testIncrement(indexer_);
+
+ // Reset the indexer
+ indexer_.reset();
+
+ // Now it should startfrom zero again
+ for (uint32_t i = 0; i < 4096; i++) {
+ auto index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, i);
+ }
+}
+
+TEST_F(IncrementalIndexerTest, TestGetSuffix) { testIncrement(indexer_); }
+
+TEST_F(IncrementalIndexerTest, TestGetNextReassemblySegment) {
+ // Test suffixes for reassembly are not influenced by download suffixed
+ // increment
+ for (uint32_t i = 0; i < 4096; i++) {
+ auto index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, i);
+ }
+
+ for (uint32_t i = 0; i < 4096; i++) {
+ auto index = indexer_.getNextReassemblySegment();
+ EXPECT_EQ(index, i);
+ }
+}
+
+TEST_F(IncrementalIndexerTest, TestJumpToIndex) { testJump(indexer_); }
+
+TEST_F(IncrementalIndexerTest, TestGetFinalSuffix) {
+ // Since final suffix hasn't been discovered, it should be invalid_index
+ auto final_suffix = indexer_.getFinalSuffix();
+ ASSERT_EQ(final_suffix, Indexer::invalid_index);
+}
+
+TEST_F(IncrementalIndexerTest, TestMaxLimit) {
+ // Jump to max value for uint32_t
+ indexer_.jumpToIndex(std::numeric_limits<uint32_t>::max());
+ auto ret = indexer_.getNextSuffix();
+ ASSERT_EQ(ret, Indexer::invalid_index);
+
+ // Now the indexer should always return invalid_index
+ for (uint32_t i = 0; i < 4096; i++) {
+ ret = indexer_.getNextSuffix();
+ EXPECT_EQ(ret, Indexer::invalid_index);
+ }
+}
+
+TEST_F(IncrementalIndexerTest, TestSetFirstSuffix) {
+ // Set first suffix before starting
+ uint32_t start = 1234567890;
+ indexer_.setFirstSuffix(1234567890);
+
+ // The first suffix set should take place only after a reset
+ auto index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, uint32_t(0));
+
+ indexer_.reset();
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, start);
+}
+
+TEST_F(IncrementalIndexerTest, TestIsFinalSuffixDiscovered) {
+ // Final suffix should not be discovererd
+ auto ret = indexer_.isFinalSuffixDiscovered();
+ EXPECT_FALSE(ret);
+}
+
+TEST_F(RtcIndexerTest, TestReset) {
+ // Without setting anything this indexer should behave exactly as the
+ // incremental indexer for the getNextSuffix()
+ testIncrement(indexer_);
+
+ // Reset the indexer
+ indexer_.reset();
+
+ // Now it should startfrom zero again
+ for (uint32_t i = 0; i < 4096; i++) {
+ auto index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, i);
+ }
+}
+
+TEST_F(RtcIndexerTest, TestGetNextSuffix) {
+ // Without setting anything this indexer should behave exactly as the
+ // incremental indexer for the getNextSuffix()
+ testIncrement(indexer_);
+}
+
+TEST_F(RtcIndexerTest, TestGetNextReassemblySegment) {
+ // This indexer should not provide reassembly segments since they are not
+ // required for rtc
+ try {
+ indexer_.getNextReassemblySegment();
+ // We should not reach this point
+ FAIL() << "Exception expected here";
+ } catch (const errors::RuntimeException &exc) {
+ // OK correct exception
+ } catch (...) {
+ FAIL() << "Wrong exception thrown";
+ }
+}
+
+TEST_F(RtcIndexerTest, TestGetFinalSuffix) {
+ // Final suffix should be eqaul to LIMIT
+ ASSERT_EQ(indexer_.getFinalSuffix(), uint32_t(LIMIT));
+}
+
+TEST_F(RtcIndexerTest, TestJumpToIndex) { testJump(indexer_); }
+
+TEST_F(RtcIndexerTest, TestIsFinalSuffixDiscovered) {
+ // This method should always return true
+ EXPECT_TRUE(indexer_.isFinalSuffixDiscovered());
+}
+
+TEST_F(RtcIndexerTest, TestMaxLimit) {
+ // Once reached the LIMIT, this indexer should restart from 0
+
+ // Jump to max value for uint32_t
+ indexer_.jumpToIndex(LIMIT);
+ testIncrement(indexer_);
+}
+
+TEST_F(RtcIndexerTest, TestEnableFec) {
+ // Here we enable the FEC and we check we receive indexes for souece packets
+ // only
+ indexer_.enableFec(fec::FECType::RS_K1_N3);
+
+ // We did not set NFec, which should be zero. So we get only indexes for
+ // Source packets.
+
+ // With this FEC type we should get one source packet every 3 (0 . . 3 . . 6)
+ auto index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, uint32_t(0));
+
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, uint32_t(3));
+
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, uint32_t(6));
+
+ // Change FEC Type
+ indexer_.enableFec(fec::FECType::RS_K10_N30);
+
+ // With this FEC type we should get source packets from 7 to 9
+ for (uint32_t i = 7; i < 10; i++) {
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, i);
+ }
+
+ // And then jump to 30
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, uint32_t(30));
+
+ // Let's now jump to a high value
+ indexer_.jumpToIndex(12365);
+ for (uint32_t i = 12365; i < 12369; i++) {
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(index, i);
+ }
+}
+
+TEST_F(RtcIndexerTest, TestSetNFec) {
+ // Here we enable the FEC and we set a max of 20 fec packets
+ indexer_.enableFec(fec::FECType::RS_K10_N90);
+ indexer_.setNFec(20);
+
+ // We should get indexes up to 29
+ uint32_t index;
+ for (uint32_t i = 0; i < 30; i++) {
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(i, index);
+ }
+
+ // Then it should jump to 90
+ for (uint32_t i = 90; i < 99; i++) {
+ index = indexer_.getNextSuffix();
+ EXPECT_EQ(i, index);
+ }
+
+ // Let's set NFEC > 80
+ indexer_.setNFec(150);
+}
+
+TEST_F(RtcIndexerTest, TestSetNFecWithOffset) {
+ // Here we enable the FEC and we set a max of 20 fec packets
+ const constexpr uint32_t first_suffix = 7;
+ indexer_.setFirstSuffix(first_suffix);
+ indexer_.reset();
+ indexer_.enableFec(fec::FECType::RS_K16_N24);
+ indexer_.setNFec(8);
+
+ uint32_t index;
+ for (uint32_t i = first_suffix; i < 16 + first_suffix; i++) {
+ index = indexer_.getNextSuffix();
+ EXPECT_FALSE(indexer_.isFec(index));
+ EXPECT_EQ(i, index);
+ }
+
+ for (uint32_t i = first_suffix + 16; i < 16 + 8 + first_suffix; i++) {
+ index = indexer_.getNextSuffix();
+ EXPECT_TRUE(indexer_.isFec(index));
+ EXPECT_EQ(i, index);
+ }
+}
+
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/test/test_interest.cc b/libtransport/src/test/test_interest.cc
index 0a835db24..8853563b0 100644
--- a/libtransport/src/test/test_interest.cc
+++ b/libtransport/src/test/test_interest.cc
@@ -260,8 +260,3 @@ TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) {
} // namespace core
} // namespace transport
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-} \ No newline at end of file
diff --git a/libtransport/src/test/test_packet.cc b/libtransport/src/test/test_packet.cc
index 0ee140e2c..76ad352d6 100644
--- a/libtransport/src/test/test_packet.cc
+++ b/libtransport/src/test/test_packet.cc
@@ -47,10 +47,6 @@ class PacketForTest : public Packet {
throw errors::NotImplementedException();
}
- void setName(Name &&name) override {
- throw errors::NotImplementedException();
- }
-
void setLifetime(uint32_t lifetime) override {
throw errors::NotImplementedException();
}
@@ -1040,8 +1036,3 @@ TEST_F(PacketTest, TestSetGetTTL) {
} // namespace core
} // namespace transport
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/libtransport/src/test/test_transport_producer.cc b/libtransport/src/test/test_transport_producer.cc
deleted file mode 100644
index f711fb4bb..000000000
--- a/libtransport/src/test/test_transport_producer.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gtest/gtest.h>
-
-#include <random>
-
-#include "hicn/transport/interfaces/socket_producer.h"
-
-namespace transport {
-
-namespace interface {
-
-namespace {
-// The fixture for testing class Foo.
-class ProducerTest : public ::testing::Test {
- protected:
- ProducerTest() : name_("b001::123|321"), producer_() {
- // You can do set-up work for each test here.
- }
-
- virtual ~ProducerTest() {
- // You can do clean-up work that doesn't throw exceptions here.
- }
-
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
-
- virtual void SetUp() {
- // Code here will be called immediately after the constructor (right
- // before each test).
- }
-
- virtual void TearDown() {
- // Code here will be called immediately after each test (right
- // before the destructor).
- }
-
- Name name_;
- ProducerSocket producer_;
-};
-
-} // namespace
-
-TEST_F(ProducerTest, ProduceContent) { ASSERT_TRUE(true); }
-
-} // namespace interface
-
-} // namespace transport
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-} \ No newline at end of file
diff --git a/libtransport/src/transport.config b/libtransport/src/transport.config
index a21175b8d..89db204d5 100644
--- a/libtransport/src/transport.config
+++ b/libtransport/src/transport.config
@@ -1,27 +1,61 @@
// Configuration for io_module
-
io_module = {
path = [];
name = "forwarder_module";
};
+// Configuration for forwarder io_module
forwarder = {
n_threads = 1;
-
- listeners = {
- l0 = {
- local_address = "127.0.0.1";
- local_port = 33436;
- }
- };
connectors = {
c0 = {
/* local_address and local_port are optional */
local_address = "127.0.0.1";
local_port = 33436;
- remote_address = "10.20.30.40";
+ remote_address = "127.0.0.1";
remote_port = 33436;
}
};
+
+ listeners = {
+ l0 = {
+ local_address = "127.0.0.1";
+ local_port = 33437;
+ }
+ };
+};
+
+// Logging
+log = {
+ // Log level (INFO (0), WARNING (1), ERROR (2), FATAL (3))
+ minloglevel = 0;
+
+ // Verbosity level for debug logs
+ v= 2;
+
+ // Log to stderr
+ logtostderr = true;
+
+ // Get fancy colored logs
+ colorlogtostderr = true;
+
+ // Log messages above this level also to stderr
+ stderrthreshold = 2;
+
+ // Set log prefix for each line log
+ log_prefix = true;
+
+ // Log dir
+ log_dir = "/tmp";
+
+ // Log only specific modules.
+ // Example: "membuf=2,rtc=3"
+ vmodule = "";
+
+ // Max log size in MB
+ max_log_size = 10;
+
+ // Log rotation
+ stop_logging_if_full_disk = true;
}; \ No newline at end of file
diff --git a/libtransport/src/utils/CMakeLists.txt b/libtransport/src/utils/CMakeLists.txt
index 1a23459b5..a85ab16bf 100644
--- a/libtransport/src/utils/CMakeLists.txt
+++ b/libtransport/src/utils/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/string_tokenizer.cc
${CMAKE_CURRENT_SOURCE_DIR}/uri.cc
diff --git a/libtransport/src/utils/content_store.cc b/libtransport/src/utils/content_store.cc
index c5cb91149..8ae7fd4d4 100644
--- a/libtransport/src/utils/content_store.cc
+++ b/libtransport/src/utils/content_store.cc
@@ -13,10 +13,10 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/core/name.h>
-#include <hicn/transport/utils/log.h>
#include <utils/content_store.h>
namespace utils {
@@ -36,9 +36,9 @@ void ContentStore::insert(
if (TRANSPORT_EXPECT_FALSE(content_store_hash_table_.size() !=
fifo_list_.size())) {
- TRANSPORT_LOGW("Inconsistent size!!!!");
- TRANSPORT_LOGW("Hash Table: %zu |||| FIFO List: %zu",
- content_store_hash_table_.size(), fifo_list_.size());
+ LOG(WARNING) << "Inconsistent size!!!!";
+ LOG(WARNING) << "Hash Table: " << content_store_hash_table_.size()
+ << " |||| FIFO List: " << fifo_list_.size();
}
if (content_store_hash_table_.size() >= max_content_store_size_) {
@@ -59,11 +59,11 @@ void ContentStore::insert(
ObjectTimeEntry(content_object, std::chrono::steady_clock::now()), pos);
}
-std::shared_ptr<ContentObject> ContentStore::find(const Interest &interest) {
+std::shared_ptr<ContentObject> ContentStore::find(const Name &name) {
utils::SpinLock::Acquire locked(cs_mutex_);
std::shared_ptr<ContentObject> ret = empty_reference_;
- auto it = content_store_hash_table_.find(interest.getName());
+ auto it = content_store_hash_table_.find(name);
if (it != content_store_hash_table_.end()) {
auto content_lifetime = it->second.first.first->getLifetime();
auto time_passed_since_creation =
@@ -108,13 +108,11 @@ void ContentStore::printContent() {
for (auto &item : content_store_hash_table_) {
if (item.second.first.first->getPayloadType() ==
transport::core::PayloadType::MANIFEST) {
- TRANSPORT_LOGI("Manifest: %s",
- item.second.first.first->getName().toString().c_str());
+ LOG(INFO) << "Manifest: " << item.second.first.first->getName();
} else {
- TRANSPORT_LOGI("Data Packet: %s",
- item.second.first.first->getName().toString().c_str());
+ LOG(INFO) << "Data Packet: " << item.second.first.first->getName();
}
}
}
-} // end namespace utils \ No newline at end of file
+} // end namespace utils
diff --git a/libtransport/src/utils/content_store.h b/libtransport/src/utils/content_store.h
index 56cd2abb6..abe5e7f6c 100644
--- a/libtransport/src/utils/content_store.h
+++ b/libtransport/src/utils/content_store.h
@@ -52,7 +52,7 @@ class ContentStore {
void insert(const std::shared_ptr<ContentObject> &content_object);
- std::shared_ptr<ContentObject> find(const Interest &interest);
+ std::shared_ptr<ContentObject> find(const Name &name);
void erase(const Name &exact_name);
@@ -73,4 +73,4 @@ class ContentStore {
mutable utils::SpinLock cs_mutex_;
};
-} // end namespace utils \ No newline at end of file
+} // end namespace utils
diff --git a/libtransport/src/utils/daemonizator.cc b/libtransport/src/utils/daemonizator.cc
index bc7bae700..6cb7d16ba 100644
--- a/libtransport/src/utils/daemonizator.cc
+++ b/libtransport/src/utils/daemonizator.cc
@@ -14,9 +14,9 @@
*/
#ifndef _WIN32
+#include <glog/logging.h>
#include <hicn/transport/errors/runtime_exception.h>
#include <hicn/transport/utils/daemonizator.h>
-#include <hicn/transport/utils/log.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -36,7 +36,7 @@ void Daemonizator::daemonize(bool close_fds) {
// PARENT PROCESS. Need to kill it.
if (process_id > 0) {
- TRANSPORT_LOGE("Process id of child process %d", process_id);
+ LOG(ERROR) << "Process id of child process " << process_id;
// return success in exit status
exit(EXIT_SUCCESS);
}
diff --git a/libtransport/src/utils/epoll_event_reactor.cc b/libtransport/src/utils/epoll_event_reactor.cc
index eb8c65352..457727bbe 100644
--- a/libtransport/src/utils/epoll_event_reactor.cc
+++ b/libtransport/src/utils/epoll_event_reactor.cc
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/utils/branch_prediction.h>
#include <signal.h>
#include <unistd.h>
@@ -30,7 +31,7 @@ EpollEventReactor::~EpollEventReactor() { close(epoll_fd_); }
int EpollEventReactor::addFileDescriptor(int fd, uint32_t events) {
if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
- TRANSPORT_LOGE("invalid fd %d", fd);
+ LOG(ERROR) << "invalid fd " << fd;
return -1;
}
@@ -41,7 +42,7 @@ int EpollEventReactor::addFileDescriptor(int fd, uint32_t events) {
if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &evt) <
0)) {
- TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd);
+ LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
return -1;
}
@@ -50,7 +51,7 @@ int EpollEventReactor::addFileDescriptor(int fd, uint32_t events) {
int EpollEventReactor::modFileDescriptor(int fd, uint32_t events) {
if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
- TRANSPORT_LOGE("invalid fd %d", fd);
+ LOG(ERROR) << "invalid fd " << fd;
return -1;
}
@@ -61,7 +62,7 @@ int EpollEventReactor::modFileDescriptor(int fd, uint32_t events) {
if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) <
0)) {
- TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd);
+ LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
return -1;
}
@@ -72,7 +73,7 @@ std::size_t EpollEventReactor::mapSize() { return event_callback_map_.size(); }
int EpollEventReactor::delFileDescriptor(int fd) {
if (TRANSPORT_EXPECT_FALSE(fd < 0)) {
- TRANSPORT_LOGE("invalid fd %d", fd);
+ LOG(ERROR) << "invalid fd " << fd;
return -1;
}
@@ -81,7 +82,7 @@ int EpollEventReactor::delFileDescriptor(int fd) {
if (TRANSPORT_EXPECT_FALSE(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &evt) <
0)) {
- TRANSPORT_LOGE("epoll_ctl: %s fd %d", strerror(errno), fd);
+ LOG(ERROR) << "epoll_ctl: " << strerror(errno) << " fd " << fd;
return -1;
}
@@ -106,7 +107,7 @@ void EpollEventReactor::runEventLoop(int timeout) {
en = epoll_pwait(epoll_fd_, evt, 128, timeout, &sigset);
if (TRANSPORT_EXPECT_FALSE(en < 0)) {
- TRANSPORT_LOGE("epoll_pwait: %s", strerror(errno));
+ LOG(ERROR) << "epoll_pwait: " << strerror(errno);
if (errno == EINTR) {
continue;
} else {
@@ -122,7 +123,7 @@ void EpollEventReactor::runEventLoop(int timeout) {
}
if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
- TRANSPORT_LOGE("unexpected event. fd %d", evt[i].data.fd);
+ LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd;
} else {
{
utils::SpinLock::Acquire locked(event_callback_map_lock_);
@@ -138,7 +139,7 @@ void EpollEventReactor::runEventLoop(int timeout) {
}
}
} else {
- TRANSPORT_LOGE("unexpected event. fd %d", evt[i].data.fd);
+ LOG(ERROR) << "unexpected event. fd " << evt[i].data.fd;
}
}
}
@@ -159,7 +160,7 @@ void EpollEventReactor::runOneEvent() {
en = epoll_pwait(epoll_fd_, &evt, 1, -1, &sigset);
if (TRANSPORT_EXPECT_FALSE(en < 0)) {
- TRANSPORT_LOGE("epoll_pwait: %s", strerror(errno));
+ LOG(ERROR) << "epoll_pwait: " << strerror(errno);
return;
}
@@ -170,7 +171,7 @@ void EpollEventReactor::runOneEvent() {
}
if (TRANSPORT_EXPECT_FALSE(it == event_callback_map_.end())) {
- TRANSPORT_LOGE("unexpected event. fd %d", evt.data.fd);
+ LOG(ERROR) << "unexpected event. fd " << evt.data.fd;
} else {
{
utils::SpinLock::Acquire locked(event_callback_map_lock_);
@@ -180,7 +181,7 @@ void EpollEventReactor::runOneEvent() {
callback(evt);
}
} else {
- TRANSPORT_LOGE("unexpected event. fd %d", evt.data.fd);
+ LOG(ERROR) << "unexpected event. fd " << evt.data.fd;
}
}
diff --git a/libtransport/src/utils/fd_deadline_timer.h b/libtransport/src/utils/fd_deadline_timer.h
index 38396e027..22c13a763 100644
--- a/libtransport/src/utils/fd_deadline_timer.h
+++ b/libtransport/src/utils/fd_deadline_timer.h
@@ -16,7 +16,6 @@
#pragma once
#include <hicn/transport/errors/runtime_exception.h>
-#include <hicn/transport/utils/log.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <utils/deadline_timer.h>
@@ -58,7 +57,7 @@ class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> {
std::error_code ec;
if (read(event.data.fd, &s, sizeof(s)) == -1) {
- TRANSPORT_LOGE("Read error!!");
+ LOG(ERROR) << "Read error!!";
}
if (!(event.events & EPOLLIN)) {
diff --git a/libtransport/src/utils/log.cc b/libtransport/src/utils/log.cc
index 27dd3f541..755d5bafa 100644
--- a/libtransport/src/utils/log.cc
+++ b/libtransport/src/utils/log.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -13,1391 +13,79 @@
* limitations under the License.
*/
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2017 wonder-mice
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* When defined, Android log (android/log.h) will be used by default instead of
- * stderr (ignored on non-Android platforms). Date, time, pid and tid (context)
- * will be provided by Android log. Android log features will be used to output
- * log level and tag.
- */
-
-#if defined(__ANDROID__)
-#define TRANSPORT_LOG_USE_ANDROID_LOG 1
-#define ANDROID_TAG "HicnTransport"
-#else
-#define TRANSPORT_LOG_USE_ANDROID_LOG 0
-#endif
-
-/* When defined, NSLog (uses Apple System Log) will be used instead of stderr
- * (ignored on non-Apple platforms). Date, time, pid and tid (context) will be
- * provided by NSLog. Curiously, doesn't use NSLog() directly, but piggybacks on
- * non-public CFLog() function. Both use Apple System Log internally, but it's
- * easier to call CFLog() from C than NSLog(). Current implementation doesn't
- * support "%@" format specifier.
- */
-#ifdef TRANSPORT_LOG_USE_NSLOG
-#undef TRANSPORT_LOG_USE_NSLOG
-#if defined(__APPLE__) && defined(__MACH__)
-#define TRANSPORT_LOG_USE_NSLOG 1
-#else
-#define TRANSPORT_LOG_USE_NSLOG 0
-#endif
-#else
-#define TRANSPORT_LOG_USE_NSLOG 0
-#endif
-/* When defined, OutputDebugString() will be used instead of stderr (ignored on
- * non-Windows platforms). Uses OutputDebugStringA() variant and feeds it with
- * UTF-8 data.
- */
-#ifdef TRANSPORT_LOG_USE_DEBUGSTRING
-#undef TRANSPORT_LOG_USE_DEBUGSTRING
-#if defined(_WIN32) || defined(_WIN64)
-#define TRANSPORT_LOG_USE_DEBUGSTRING 1
-#else
-#define TRANSPORT_LOG_USE_DEBUGSTRING 0
-#endif
-#else
-#define TRANSPORT_LOG_USE_DEBUGSTRING 0
-#endif
-/* When defined, TRANSPORT_LOG library will not contain definition of tag prefix
- * variable. In that case it must be defined elsewhere using
- * TRANSPORT_LOG_DEFINE_TAG_PREFIX macro, for example:
- *
- * TRANSPORT_LOG_DEFINE_TAG_PREFIX = "ProcessName";
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef TRANSPORT_LOG_EXTERN_TAG_PREFIX
-#undef TRANSPORT_LOG_EXTERN_TAG_PREFIX
-#define TRANSPORT_LOG_EXTERN_TAG_PREFIX 1
-#else
-#define TRANSPORT_LOG_EXTERN_TAG_PREFIX 0
-#endif
-/* When defined, TRANSPORT_LOG library will not contain definition of global
- * format variable. In that case it must be defined elsewhere using
- * TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT macro, for example:
- *
- * TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT = {MEM_WIDTH};
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT
-#undef TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT
-#define TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT 1
-#else
-#define TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT 0
-#endif
-/* When defined, transport_log library will not contain definition of global
- * output variable. In that case it must be defined elsewhere using
- * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT macro, for example:
- *
- * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {TRANSPORT_LOG_PUT_STD,
- * custom_output_callback};
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT
-#undef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT
-#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT 1
-#else
-#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT 0
-#endif
-/* When defined, transport_log library will not contain definition of global
- * output level variable. In that case it must be defined elsewhere using
- * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL macro, for example:
- *
- * TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = TRANSPORT_LOG_WARN;
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
-#undef TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
-#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL 1
-#else
-#define TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL 0
-#endif
-/* When defined, implementation will prefer smaller code size over speed.
- * Very rough estimate is that code will be up to 2x smaller and up to 2x
- * slower. Disabled by default.
- */
-#ifdef TRANSPORT_LOG_OPTIMIZE_SIZE
-#undef TRANSPORT_LOG_OPTIMIZE_SIZE
-#define TRANSPORT_LOG_OPTIMIZE_SIZE 1
-#else
-#define TRANSPORT_LOG_OPTIMIZE_SIZE 0
-#endif
-/* Size of the log line buffer. The buffer is allocated on stack. It limits
- * maximum length of a log line.
- */
-#ifndef TRANSPORT_LOG_BUF_SZ
-#define TRANSPORT_LOG_BUF_SZ 512
-#endif
-/* Default number of bytes in one line of memory output. For large values
- * TRANSPORT_LOG_BUF_SZ also must be increased.
- */
-#ifndef TRANSPORT_LOG_MEM_WIDTH
-#define TRANSPORT_LOG_MEM_WIDTH 32
-#endif
-/* String to put in the end of each log line (can be empty). Its value used by
- * stderr output callback. Its size used as a default value for
- * TRANSPORT_LOG_EOL_SZ.
- */
-#ifndef TRANSPORT_LOG_EOL
-#define TRANSPORT_LOG_EOL "\n"
-#endif
-/* Default delimiter that separates parts of log message. Can NOT contain '%'
- * or '\0'.
- *
- * Log message format specifications can override (or ignore) this value. For
- * more details see TRANSPORT_LOG_MESSAGE_CTX_FORMAT,
- * TRANSPORT_LOG_MESSAGE_SRC_FORMAT and TRANSPORT_LOG_MESSAGE_TAG_FORMAT.
- */
-#ifndef TRANSPORT_LOG_DEF_DELIMITER
-#define TRANSPORT_LOG_DEF_DELIMITER " "
-#endif
-/* Specifies log message context format. Log message context includes date,
- * time, process id, thread id and message's log level. Custom information can
- * be added as well. Supported fields: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND,
- * MILLISECOND, PID, TID, LEVEL, S(str), F_INIT(statements),
- * F_UINT(width, value).
- *
- * Must be defined as a tuple, for example:
- *
- * #define TRANSPORT_LOG_MESSAGE_CTX_FORMAT (YEAR, S("."), MONTH, S("."), DAY,
- * S(" > "))
- *
- * In that case, resulting log message will be:
- *
- * 2016.12.22 > TAG function@filename.c:line Message text
- *
- * Note, that tag, source location and message text are not impacted by
- * this setting. See TRANSPORT_LOG_MESSAGE_TAG_FORMAT and
- * TRANSPORT_LOG_MESSAGE_SRC_FORMAT.
- *
- * If message context must be visually separated from the rest of the message,
- * it must be reflected in context format (notice trailing S(" > ") in the
- * example above).
- *
- * S(str) adds constant string str. String can NOT contain '%' or '\0'.
- *
- * F_INIT(statements) adds initialization statement(s) that will be evaluated
- * once for each log message. All statements are evaluated in specified order.
- * Several F_INIT() fields can be used in every log message format
- * specification. Fields, like F_UINT(width, value), are allowed to use results
- * of initialization statements. If statement introduces variables (or other
- * names, like structures) they must be prefixed with "f_". Statements must be
- * enclosed into additional "()". Example:
- *
- * #define TRANSPORT_LOG_MESSAGE_CTX_FORMAT \
- * (F_INIT(( struct rusage f_ru; getrusage(RUSAGE_SELF, &f_ru); )), \
- * YEAR, S("."), MONTH, S("."), DAY, S(" "), \
- * F_UINT(5, f_ru.ru_nsignals), \
- * S(" "))
- *
- * F_UINT(width, value) adds unsigned integer value extended with up to width
- * spaces (for alignment purposes). Value can be any expression that evaluates
- * to unsigned integer. If expression contains non-standard functions, they
- * must be declared with F_INIT(). Example:
- *
- * #define TRANSPORT_LOG_MESSAGE_CTX_FORMAT \
- * (YEAR, S("."), MONTH, S("."), DAY, S(" "), \
- * F_INIT(( unsigned tickcount(); )), \
- * F_UINT(5, tickcount()), \
- * S(" "))
- *
- * Other log message format specifications follow same rules, but have a
- * different set of supported fields.
- */
-#ifndef TRANSPORT_LOG_MESSAGE_CTX_FORMAT
-#define TRANSPORT_LOG_MESSAGE_CTX_FORMAT \
- (MONTH, S("-"), DAY, S(TRANSPORT_LOG_DEF_DELIMITER), HOUR, S(":"), MINUTE, \
- S(":"), SECOND, S("."), MILLISECOND, S(TRANSPORT_LOG_DEF_DELIMITER), PID, \
- S(TRANSPORT_LOG_DEF_DELIMITER), TID, S(TRANSPORT_LOG_DEF_DELIMITER), LEVEL, \
- S(TRANSPORT_LOG_DEF_DELIMITER))
-#endif
-/* Example:
- */
-/* Specifies log message tag format. It includes tag prefix and tag. Custom
- * information can be added as well. Supported fields:
- * TAG(prefix_delimiter, tag_delimiter), S(str), F_INIT(statements),
- * F_UINT(width, value).
- *
- * TAG(prefix_delimiter, tag_delimiter) adds following string to log message:
- *
- * PREFIX<prefix_delimiter>TAG<tag_delimiter>
- *
- * Prefix delimiter will be used only when prefix is not empty. Tag delimiter
- * will be used only when prefixed tag is not empty. Example:
- *
- * #define TRANSPORT_LOG_TAG_FORMAT (S("["), TAG(".", ""), S("] "))
- *
- * See TRANSPORT_LOG_MESSAGE_CTX_FORMAT for details.
- */
-#ifndef TRANSPORT_LOG_MESSAGE_TAG_FORMAT
-#define TRANSPORT_LOG_MESSAGE_TAG_FORMAT (TAG(".", TRANSPORT_LOG_DEF_DELIMITER))
-#endif
-/* Specifies log message source location format. It includes function name,
- * file name and file line. Custom information can be added as well. Supported
- * fields: FUNCTION, FILENAME, FILELINE, S(str), F_INIT(statements),
- * F_UINT(width, value).
- *
- * See TRANSPORT_LOG_MESSAGE_CTX_FORMAT for details.
- */
-#ifndef TRANSPORT_LOG_MESSAGE_SRC_FORMAT
-#define TRANSPORT_LOG_MESSAGE_SRC_FORMAT \
- (FUNCTION, S("@"), FILENAME, S(":"), FILELINE, S(TRANSPORT_LOG_DEF_DELIMITER))
-#endif
-/* Fields that can be used in log message format specifications (see above).
- * Mentioning them here explicitly, so we know that nobody else defined them
- * before us. See TRANSPORT_LOG_MESSAGE_CTX_FORMAT for details.
- */
-#define YEAR YEAR
-#define MONTH MONTH
-#define DAY DAY
-#define MINUTE MINUTE
-#define SECOND SECOND
-#define MILLISECOND MILLISECOND
-#define PID PID
-#define TID TID
-#define LEVEL LEVEL
-#define TAG(prefix_delim, tag_delim) TAG(prefix_delim, tag_delim)
-#define FUNCTION FUNCTION
-#define FILENAME FILENAME
-#define FILELINE FILELINE
-#define S(str) S(str)
-#define F_INIT(statements) F_INIT(statements)
-#define F_UINT(width, value) F_UINT(width, value)
-/* Number of bytes to reserve for EOL in the log line buffer (must be >0).
- * Must be larger than or equal to length of TRANSPORT_LOG_EOL with terminating
- * null.
- */
-#ifndef TRANSPORT_LOG_EOL_SZ
-#define TRANSPORT_LOG_EOL_SZ sizeof(TRANSPORT_LOG_EOL)
-#endif
-/* Compile instrumented version of the library to facilitate unit testing.
- */
-#ifndef TRANSPORT_LOG_INSTRUMENTED
-#define TRANSPORT_LOG_INSTRUMENTED 0
-#endif
+#define GLOG_CUSTOM_PREFIX_SUPPORT 1
+#include <glog/logging.h>
+#undef GLOG_CUSTOM_PREFIX_SUPPORT
-#if defined(__linux__)
-#if !defined(__ANDROID__) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#endif
-#if defined(__MINGW32__)
-#ifdef __STRICT_ANSI__
-#undef __STRICT_ANSI__
-#endif
-#endif
-
-#include <assert.h>
-#include <ctype.h>
+#include <core/global_configuration.h>
+#include <hicn/transport/config.h>
#include <hicn/transport/utils/log.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#if defined(_WIN32) || defined(_WIN64)
-#include <windows.h>
-#else
-#include <sys/time.h>
-#include <unistd.h>
-#if defined(__linux__)
-#include <linux/limits.h>
-#else
-#include <sys/syslimits.h>
-#endif
-#endif
-
-#if defined(__linux__)
-#include <sys/prctl.h>
-#include <sys/types.h>
-#if !defined(__ANDROID__)
-#include <sys/syscall.h>
-#endif
-#endif
-#if defined(__MACH__)
-#include <pthread.h>
-#endif
-
-#define INLINE _TRANSPORT_LOG_INLINE
-#define VAR_UNUSED(var) (void)var
-#define RETVAL_UNUSED(expr) \
- do { \
- while (expr) break; \
- } while (0)
-#define STATIC_ASSERT(name, cond) typedef char assert_##name[(cond) ? 1 : -1]
-#define ASSERT_UNREACHABLE(why) assert(!sizeof(why))
-#ifndef _countof
-#define _countof(xs) (sizeof(xs) / sizeof((xs)[0]))
-#endif
-
-#if TRANSPORT_LOG_INSTRUMENTED
-#define INSTRUMENTED_CONST
-#else
-#define INSTRUMENTED_CONST const
-#endif
-
-#define _PP_PASTE_2(a, b) a##b
-#define _PP_CONCAT_2(a, b) _PP_PASTE_2(a, b)
-
-#define _PP_PASTE_3(a, b, c) a##b##c
-#define _PP_CONCAT_3(a, b, c) _PP_PASTE_3(a, b, c)
-
-/* Microsoft C preprocessor is a piece of shit. This moron treats __VA_ARGS__
- * as a single token and requires additional expansion to realize that it's
- * actually a list. If not for it, there would be no need in this extra
- * expansion.
- */
-#define _PP_ID(x) x
-#define _PP_NARGS_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
- _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, \
- _24, ...) \
- _24
-#define _PP_NARGS(...) \
- _PP_ID(_PP_NARGS_N(__VA_ARGS__, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, \
- 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
-
-/* There is a more efficient way to implement this, but it requires
- * working C preprocessor. Unfortunately, Microsoft Visual Studio doesn't
- * have one.
- */
-#define _PP_HEAD__(x, ...) x
-#define _PP_HEAD_(...) _PP_ID(_PP_HEAD__(__VA_ARGS__, ~))
-#define _PP_HEAD(xs) _PP_HEAD_ xs
-#define _PP_TAIL_(x, ...) (__VA_ARGS__)
-#define _PP_TAIL(xs) _PP_TAIL_ xs
-#define _PP_UNTUPLE_(...) __VA_ARGS__
-#define _PP_UNTUPLE(xs) _PP_UNTUPLE_ xs
-
-/* Apply function macro to each element in tuple. Output is not
- * enforced to be a tuple.
- */
-#define _PP_MAP_1(f, xs) f(_PP_HEAD(xs))
-#define _PP_MAP_2(f, xs) f(_PP_HEAD(xs)) _PP_MAP_1(f, _PP_TAIL(xs))
-#define _PP_MAP_3(f, xs) f(_PP_HEAD(xs)) _PP_MAP_2(f, _PP_TAIL(xs))
-#define _PP_MAP_4(f, xs) f(_PP_HEAD(xs)) _PP_MAP_3(f, _PP_TAIL(xs))
-#define _PP_MAP_5(f, xs) f(_PP_HEAD(xs)) _PP_MAP_4(f, _PP_TAIL(xs))
-#define _PP_MAP_6(f, xs) f(_PP_HEAD(xs)) _PP_MAP_5(f, _PP_TAIL(xs))
-#define _PP_MAP_7(f, xs) f(_PP_HEAD(xs)) _PP_MAP_6(f, _PP_TAIL(xs))
-#define _PP_MAP_8(f, xs) f(_PP_HEAD(xs)) _PP_MAP_7(f, _PP_TAIL(xs))
-#define _PP_MAP_9(f, xs) f(_PP_HEAD(xs)) _PP_MAP_8(f, _PP_TAIL(xs))
-#define _PP_MAP_10(f, xs) f(_PP_HEAD(xs)) _PP_MAP_9(f, _PP_TAIL(xs))
-#define _PP_MAP_11(f, xs) f(_PP_HEAD(xs)) _PP_MAP_10(f, _PP_TAIL(xs))
-#define _PP_MAP_12(f, xs) f(_PP_HEAD(xs)) _PP_MAP_11(f, _PP_TAIL(xs))
-#define _PP_MAP_13(f, xs) f(_PP_HEAD(xs)) _PP_MAP_12(f, _PP_TAIL(xs))
-#define _PP_MAP_14(f, xs) f(_PP_HEAD(xs)) _PP_MAP_13(f, _PP_TAIL(xs))
-#define _PP_MAP_15(f, xs) f(_PP_HEAD(xs)) _PP_MAP_14(f, _PP_TAIL(xs))
-#define _PP_MAP_16(f, xs) f(_PP_HEAD(xs)) _PP_MAP_15(f, _PP_TAIL(xs))
-#define _PP_MAP_17(f, xs) f(_PP_HEAD(xs)) _PP_MAP_16(f, _PP_TAIL(xs))
-#define _PP_MAP_18(f, xs) f(_PP_HEAD(xs)) _PP_MAP_17(f, _PP_TAIL(xs))
-#define _PP_MAP_19(f, xs) f(_PP_HEAD(xs)) _PP_MAP_18(f, _PP_TAIL(xs))
-#define _PP_MAP_20(f, xs) f(_PP_HEAD(xs)) _PP_MAP_19(f, _PP_TAIL(xs))
-#define _PP_MAP_21(f, xs) f(_PP_HEAD(xs)) _PP_MAP_20(f, _PP_TAIL(xs))
-#define _PP_MAP_22(f, xs) f(_PP_HEAD(xs)) _PP_MAP_21(f, _PP_TAIL(xs))
-#define _PP_MAP_23(f, xs) f(_PP_HEAD(xs)) _PP_MAP_22(f, _PP_TAIL(xs))
-#define _PP_MAP_24(f, xs) f(_PP_HEAD(xs)) _PP_MAP_23(f, _PP_TAIL(xs))
-#define _PP_MAP(f, xs) _PP_CONCAT_2(_PP_MAP_, _PP_NARGS xs)(f, xs)
-
-/* Apply function macro to each element in tuple in reverse order.
- * Output is not enforced to be a tuple.
- */
-#define _PP_RMAP_1(f, xs) f(_PP_HEAD(xs))
-#define _PP_RMAP_2(f, xs) _PP_RMAP_1(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_3(f, xs) _PP_RMAP_2(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_4(f, xs) _PP_RMAP_3(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_5(f, xs) _PP_RMAP_4(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_6(f, xs) _PP_RMAP_5(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_7(f, xs) _PP_RMAP_6(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_8(f, xs) _PP_RMAP_7(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_9(f, xs) _PP_RMAP_8(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_10(f, xs) _PP_RMAP_9(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_11(f, xs) _PP_RMAP_10(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_12(f, xs) _PP_RMAP_11(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_13(f, xs) _PP_RMAP_12(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_14(f, xs) _PP_RMAP_13(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_15(f, xs) _PP_RMAP_14(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_16(f, xs) _PP_RMAP_15(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_17(f, xs) _PP_RMAP_16(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_18(f, xs) _PP_RMAP_17(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_19(f, xs) _PP_RMAP_18(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_20(f, xs) _PP_RMAP_19(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_21(f, xs) _PP_RMAP_20(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_22(f, xs) _PP_RMAP_21(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_23(f, xs) _PP_RMAP_22(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_24(f, xs) _PP_RMAP_23(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP(f, xs) _PP_CONCAT_2(_PP_RMAP_, _PP_NARGS xs)(f, xs)
-
-/* Used to implement _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS() macro. All
- * possible fields must be mentioned here. Not counting F_INIT() here because
- * it's somewhat special and is handled spearatly (at least for now).
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__ (0 << 0)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__YEAR (1 << 1)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__MONTH (1 << 2)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__DAY (1 << 3)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__HOUR (1 << 4)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__MINUTE (1 << 5)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__SECOND (1 << 6)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__MILLISECOND (1 << 7)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__PID (1 << 8)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__TID (1 << 9)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__LEVEL (1 << 10)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__TAG(ps, ts) (1 << 11)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__FUNCTION (1 << 12)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__FILENAME (1 << 13)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__FILELINE (1 << 14)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__S(s) (1 << 15)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__F_INIT(expr) (0 << 16)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK__F_UINT(w, v) (1 << 17)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_MASK(field) \
- _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_MASK_, _, field)
-
-/* Logical "or" of masks of fields used in specified format specification.
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(format) \
- (0 _PP_MAP(| _TRANSPORT_LOG_MESSAGE_FORMAT_MASK, format))
-
-/* Expands to expressions that evaluates to true if field is used in
- * specified format specification. Example:
- *
- * #if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(F_UINT,
- * TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
- * ...
- * #endif
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, format) \
- (_TRANSPORT_LOG_MESSAGE_FORMAT_MASK(field) & \
- _TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(format))
-
-/* Same, but checks all supported format specifications.
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_FIELD_USED(field) \
- (_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, \
- TRANSPORT_LOG_MESSAGE_TAG_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(field, \
- TRANSPORT_LOG_MESSAGE_SRC_FORMAT))
-
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_DATETIME_USED \
- (_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(YEAR, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(MONTH, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(DAY, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(HOUR, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(MINUTE, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(SECOND, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(MILLISECOND, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT))
-
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
-#pragma warning(disable : 4204) /* nonstandard extension used: non-constant \
- aggregate initializer */
-#define memccpy _memccpy
-#endif
-
-#if (defined(_MSC_VER) && !defined(__INTEL_COMPILER)) || defined(__MINGW64__)
-#define vsnprintf(s, sz, fmt, va) fake_vsnprintf(s, sz, fmt, va)
-static int fake_vsnprintf(char *s, size_t sz, const char *fmt, va_list ap) {
- const int n = vsnprintf_s(s, sz, _TRUNCATE, fmt, ap);
- return 0 < n ? n : (int)sz + 1; /* no need in _vscprintf() for now */
-}
-#if TRANSPORT_LOG_OPTIMIZE_SIZE
-#define snprintf(s, sz, ...) fake_snprintf(s, sz, __VA_ARGS__)
-static int fake_snprintf(char *s, size_t sz, const char *fmt, ...) {
- va_list va;
- va_start(va, fmt);
- const int n = fake_vsnprintf(s, sz, fmt, va);
- va_end(va);
- return n;
-}
-#endif
-#endif
-
-typedef void (*time_cb)(struct tm *const tm, unsigned *const usec);
-typedef void (*pid_cb)(int *const pid, int *const tid);
-typedef void (*buffer_cb)(transport_log_message *msg, char *buf);
-
-typedef struct src_location {
- const char *const func;
- const char *const file;
- const unsigned line;
-} src_location;
-
-typedef struct mem_block {
- const void *const d;
- const unsigned d_sz;
-} mem_block;
-
-static void time_callback(struct tm *const tm, unsigned *const usec);
-static void pid_callback(int *const pid, int *const tid);
-static void buffer_callback(transport_log_message *msg, char *buf);
-
-STATIC_ASSERT(eol_fits_eol_sz,
- sizeof(TRANSPORT_LOG_EOL) <= TRANSPORT_LOG_EOL_SZ);
-STATIC_ASSERT(eol_sz_greater_than_zero, 0 < TRANSPORT_LOG_EOL_SZ);
-STATIC_ASSERT(eol_sz_less_than_buf_sz,
- TRANSPORT_LOG_EOL_SZ < TRANSPORT_LOG_BUF_SZ);
-#if !defined(_WIN32) && !defined(_WIN64)
-STATIC_ASSERT(buf_sz_less_than_pipe_buf, TRANSPORT_LOG_BUF_SZ <= PIPE_BUF);
-#endif
-static const char c_hex[] = "0123456789abcdef";
-
-static INSTRUMENTED_CONST unsigned g_buf_sz =
- TRANSPORT_LOG_BUF_SZ - TRANSPORT_LOG_EOL_SZ;
-static INSTRUMENTED_CONST time_cb g_time_cb = time_callback;
-static INSTRUMENTED_CONST pid_cb g_pid_cb = pid_callback;
-static INSTRUMENTED_CONST buffer_cb g_buffer_cb = buffer_callback;
-#if TRANSPORT_LOG_USE_ANDROID_LOG
-#include <android/log.h>
-
-static INLINE int android_lvl(const int lvl) {
- switch (lvl) {
- case TRANSPORT_LOG_VERBOSE:
- return ANDROID_LOG_VERBOSE;
- case TRANSPORT_LOG_DEBUG:
- return ANDROID_LOG_DEBUG;
- case TRANSPORT_LOG_INFO:
- return ANDROID_LOG_INFO;
- case TRANSPORT_LOG_WARN:
- return ANDROID_LOG_WARN;
- case TRANSPORT_LOG_ERROR:
- return ANDROID_LOG_ERROR;
- case TRANSPORT_LOG_FATAL:
- return ANDROID_LOG_FATAL;
- default:
- ASSERT_UNREACHABLE("Bad log level");
- return ANDROID_LOG_UNKNOWN;
- }
-}
-
-static void out_android_callback(const transport_log_message *const msg,
- void *arg) {
- VAR_UNUSED(arg);
- *msg->p = 0;
- const char *tag = msg->p;
- if (msg->tag_e != msg->tag_b) {
- tag = msg->tag_b;
- *msg->tag_e = 0;
+#include <iomanip>
+#include <iostream>
+#include <libconfig.h++>
+
+namespace utils {
+
+#define _(class_name, macro_name) \
+ std::ostream &CLASS_NAME(class_name)::getStream() { return macro_name; }
+foreach_log_level
+#undef _
+
+ class LogConfiguration {
+ static constexpr char log_config_section[] = "log";
+#define LOG_NAME \
+ "Libhicntransport-" HICNTRANSPORT_VERSION_MAJOR \
+ "." HICNTRANSPORT_VERSION_MINOR "." HICNTRANSPORT_VERSION_REVISION
+ static constexpr char log_name[] = LOG_NAME;
+
+#define foreach_log_config \
+ _(bool, logtostderr, true) \
+ _(bool, alsologtostderr, false) \
+ _(bool, colorlogtostderr, true) \
+ _(int32_t, stderrthreshold, 2) \
+ _(int32_t, minloglevel, 0) \
+ _(bool, log_prefix, true) \
+ _(std::string, log_dir, "") \
+ _(int32_t, v, 1) \
+ _(std::string, vmodule, "") \
+ _(int32_t, max_log_size, 5) \
+ _(bool, stop_logging_if_full_disk, true)
+
+ public:
+ LogConfiguration() {
+ auto &conf = transport::core::GlobalConfiguration::getInstance();
+
+ using namespace std::placeholders;
+ conf.registerConfigurationParser(
+ log_config_section,
+ std::bind(&LogConfiguration::parseLogConfiguration, this, _1, _2));
+ }
+
+ private:
+ void parseLogConfiguration(const libconfig::Setting &log_config,
+ std::error_code &ec) {
+#define _(type, name, default) \
+ type _##name = default; \
+ \
+ if (log_config.exists(#name)) { \
+ log_config.lookupValue(#name, _##name); \
+ VLOG(2) << "Setting log config " << #name << " to " << _##name; \
+ \
+ FLAGS_##name = _##name; \
+ } else { \
+ VLOG(2) << "Log config " << #name << " do not exists"; \
+ }
+ foreach_log_config
+#undef _
+
+ google::InitGoogleLogging(log_name);
}
- __android_log_print(android_lvl(msg->lvl), ANDROID_TAG, "%s", msg->msg_b);
-}
-
-enum { OUT_ANDROID_MASK = TRANSPORT_LOG_PUT_STD & ~TRANSPORT_LOG_PUT_CTX };
-#define OUT_ANDROID OUT_ANDROID_MASK, 0, out_android_callback
-#endif
-
-#if TRANSPORT_LOG_USE_NSLOG
-#include <CoreFoundation/CoreFoundation.h>
-CF_EXPORT void CFLog(int32_t level, CFStringRef format, ...);
-
-static INLINE int apple_lvl(const int lvl) {
- switch (lvl) {
- case TRANSPORT_LOG_VERBOSE:
- return 7; /* ASL_LEVEL_DEBUG / kCFLogLevelDebug */
- ;
- case TRANSPORT_LOG_DEBUG:
- return 7; /* ASL_LEVEL_DEBUG / kCFLogLevelDebug */
- ;
- case TRANSPORT_LOG_INFO:
- return 6; /* ASL_LEVEL_INFO / kCFLogLevelInfo */
- ;
- case TRANSPORT_LOG_WARN:
- return 4; /* ASL_LEVEL_WARNING / kCFLogLevelWarning */
- ;
- case TRANSPORT_LOG_ERROR:
- return 3; /* ASL_LEVEL_ERR / kCFLogLevelError */
- ;
- case TRANSPORT_LOG_FATAL:
- return 0; /* ASL_LEVEL_EMERG / kCFLogLevelEmergency */
- ;
- default:
- ASSERT_UNREACHABLE("Bad log level");
- return 0; /* ASL_LEVEL_EMERG / kCFLogLevelEmergency */
- ;
- }
-}
-
-static void out_nslog_callback(const transport_log_message *const msg,
- void *arg) {
- VAR_UNUSED(arg);
- *msg->p = 0;
- CFLog(apple_lvl(msg->lvl), CFSTR("%s"), msg->tag_b);
-}
-
-enum { OUT_NSLOG_MASK = TRANSPORT_LOG_PUT_STD & ~TRANSPORT_LOG_PUT_CTX };
-#define OUT_NSLOG OUT_NSLOG_MASK, 0, out_nslog_callback
-#endif
-
-#if TRANSPORT_LOG_USE_DEBUGSTRING
-#include <windows.h>
-
-static void out_debugstring_callback(const transport_log_message *const msg,
- void *arg) {
- VAR_UNUSED(arg);
- msg->p[0] = '\n';
- msg->p[1] = '\0';
- OutputDebugStringA(msg->buf);
-}
-
-enum { OUT_DEBUGSTRING_MASK = TRANSPORT_LOG_PUT_STD };
-#define OUT_DEBUGSTRING OUT_DEBUGSTRING_MASK, 0, out_debugstring_callback
-#endif
-
-void transport_log_out_stderr_callback(const transport_log_message *const msg,
- void *arg) {
- VAR_UNUSED(arg);
- const size_t eol_len = sizeof(TRANSPORT_LOG_EOL) - 1;
- memcpy(msg->p, TRANSPORT_LOG_EOL, eol_len);
-#if defined(_WIN32) || defined(_WIN64)
- /* WriteFile() is atomic for local files opened with FILE_APPEND_DATA and
- without FILE_WRITE_DATA */
- DWORD written;
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg->buf,
- (DWORD)(msg->p - msg->buf + eol_len), &written, 0);
-#else
- /* write() is atomic for buffers less than or equal to PIPE_BUF. */
- RETVAL_UNUSED(
- write(STDERR_FILENO, msg->buf, (size_t)(msg->p - msg->buf) + eol_len));
-#endif
-}
-
-static const transport_log_output out_stderr = {TRANSPORT_LOG_OUT_STDERR};
-
-#if !TRANSPORT_LOG_EXTERN_TAG_PREFIX
-TRANSPORT_LOG_DEFINE_TAG_PREFIX = 0;
-#endif
-
-#if !TRANSPORT_LOG_EXTERN_GLOBAL_FORMAT
-TRANSPORT_LOG_DEFINE_GLOBAL_FORMAT = {TRANSPORT_LOG_MEM_WIDTH};
-#endif
-
-#if !TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT
-#if TRANSPORT_LOG_USE_ANDROID_LOG
-TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_ANDROID};
-#elif TRANSPORT_LOG_USE_NSLOG
-TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_NSLOG};
-#elif TRANSPORT_LOG_USE_DEBUGSTRING
-TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_DEBUGSTRING};
-#else
-TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT = {TRANSPORT_LOG_OUT_STDERR};
-#endif
-#endif
-
-#if !TRANSPORT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
-TRANSPORT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = 0;
-#endif
-
-const transport_log_spec _transport_log_stderr_spec = {
- TRANSPORT_LOG_GLOBAL_FORMAT,
- &out_stderr,
};
-static const transport_log_spec global_spec = {
- TRANSPORT_LOG_GLOBAL_FORMAT,
- TRANSPORT_LOG_GLOBAL_OUTPUT,
-};
-
-#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(LEVEL, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
-static char lvl_char(const int lvl) {
- switch (lvl) {
- case TRANSPORT_LOG_VERBOSE:
- return 'V';
- case TRANSPORT_LOG_DEBUG:
- return 'D';
- case TRANSPORT_LOG_INFO:
- return 'I';
- case TRANSPORT_LOG_WARN:
- return 'W';
- case TRANSPORT_LOG_ERROR:
- return 'E';
- case TRANSPORT_LOG_FATAL:
- return 'F';
- default:
- ASSERT_UNREACHABLE("Bad log level");
- return '?';
- }
-}
-#endif
-
-#define GCCVER_LESS(MAJOR, MINOR, PATCH) \
- (__GNUC__ < MAJOR || (__GNUC__ == MAJOR && (__GNUC_MINOR__ < MINOR || \
- (__GNUC_MINOR__ == MINOR && \
- __GNUC_PATCHLEVEL__ < PATCH))))
-
-#if !defined(__clang__) && defined(__GNUC__) && GCCVER_LESS(4, 7, 0)
-#define __atomic_load_n(vp, model) __sync_fetch_and_add(vp, 0)
-#define __atomic_fetch_add(vp, n, model) __sync_fetch_and_add(vp, n)
-#define __atomic_sub_fetch(vp, n, model) __sync_sub_and_fetch(vp, n)
-#define __atomic_or_fetch(vp, n, model) __sync_or_and_fetch(vp, n)
-#define __atomic_and_fetch(vp, n, model) __sync_and_and_fetch(vp, n)
-/* Note: will not store old value of *vp in *ep (non-standard behaviour) */
-#define __atomic_compare_exchange_n(vp, ep, d, weak, smodel, fmodel) \
- __sync_bool_compare_and_swap(vp, *(ep), d)
-#endif
-
-#if !TRANSPORT_LOG_OPTIMIZE_SIZE && !defined(_WIN32) && !defined(_WIN64)
-#define TCACHE
-#define TCACHE_STALE (0x40000000)
-#define TCACHE_FLUID (0x40000000 | 0x80000000)
-static unsigned g_tcache_mode = TCACHE_STALE;
-static struct timeval g_tcache_tv = {0, 0};
-static struct tm g_tcache_tm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-static INLINE int tcache_get(const struct timeval *const tv,
- struct tm *const tm) {
- unsigned mode;
- mode = __atomic_load_n(&g_tcache_mode, __ATOMIC_RELAXED);
- if (0 == (mode & TCACHE_FLUID)) {
- mode = __atomic_fetch_add(&g_tcache_mode, 1, __ATOMIC_ACQUIRE);
- if (0 == (mode & TCACHE_FLUID)) {
- if (g_tcache_tv.tv_sec == tv->tv_sec) {
- *tm = g_tcache_tm;
- __atomic_sub_fetch(&g_tcache_mode, 1, __ATOMIC_RELEASE);
- return !0;
- }
- __atomic_or_fetch(&g_tcache_mode, TCACHE_STALE, __ATOMIC_RELAXED);
- }
- __atomic_sub_fetch(&g_tcache_mode, 1, __ATOMIC_RELEASE);
- }
- return 0;
-}
-
-static INLINE void tcache_set(const struct timeval *const tv,
- struct tm *const tm) {
- unsigned stale = TCACHE_STALE;
- if (__atomic_compare_exchange_n(&g_tcache_mode, &stale, TCACHE_FLUID, 0,
- __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
- g_tcache_tv = *tv;
- g_tcache_tm = *tm;
- __atomic_and_fetch(&g_tcache_mode, ~TCACHE_FLUID, __ATOMIC_RELEASE);
- }
-}
-#endif
-
-static void time_callback(struct tm *const tm, unsigned *const msec) {
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_DATETIME_USED
- VAR_UNUSED(tm);
- VAR_UNUSED(msec);
-#else
-#if defined(_WIN32) || defined(_WIN64)
- SYSTEMTIME st;
- GetLocalTime(&st);
- tm->tm_year = st.wYear;
- tm->tm_mon = st.wMonth - 1;
- tm->tm_mday = st.wDay;
- tm->tm_wday = st.wDayOfWeek;
- tm->tm_hour = st.wHour;
- tm->tm_min = st.wMinute;
- tm->tm_sec = st.wSecond;
- *msec = st.wMilliseconds;
-#else
- struct timeval tv;
- gettimeofday(&tv, 0);
-#ifndef TCACHE
- localtime_r(&tv.tv_sec, tm);
-#else
- if (!tcache_get(&tv, tm)) {
- localtime_r(&tv.tv_sec, tm);
- tcache_set(&tv, tm);
- }
-#endif
- *msec = (unsigned)tv.tv_usec / 1000;
-#endif
-#endif
-}
-
-static void pid_callback(int *const pid, int *const tid) {
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(PID, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
- VAR_UNUSED(pid);
-#else
-#if defined(_WIN32) || defined(_WIN64)
- *pid = GetCurrentProcessId();
-#else
- *pid = getpid();
-#endif
-#endif
-
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(TID, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
- VAR_UNUSED(tid);
-#else
-#if defined(_WIN32) || defined(_WIN64)
- *tid = GetCurrentThreadId();
-#elif defined(__ANDROID__)
- *tid = gettid();
-#elif defined(__linux__)
- *tid = syscall(SYS_gettid);
-#elif defined(__MACH__)
- *tid = (int)pthread_mach_thread_np(pthread_self());
-#else
-#define Platform not supported
-#endif
-#endif
-}
-
-static void buffer_callback(transport_log_message *msg, char *buf) {
- msg->e = (msg->p = msg->buf = buf) + g_buf_sz;
-}
-
-#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(FUNCTION, \
- TRANSPORT_LOG_MESSAGE_SRC_FORMAT)
-static const char *funcname(const char *func) { return func ? func : ""; }
-#endif
-
-#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(FILENAME, \
- TRANSPORT_LOG_MESSAGE_SRC_FORMAT)
-static const char *filename(const char *file) {
- const char *f = file;
- for (const char *p = file; 0 != *p; ++p) {
- if ('/' == *p || '\\' == *p) {
- f = p + 1;
- }
- }
- return f;
-}
-#endif
-
-static INLINE size_t nprintf_size(transport_log_message *const msg) {
- // *nprintf() always puts 0 in the end when input buffer is not empty. This
- // 0 is not desired because its presence sets (ctx->p) to (ctx->e - 1) which
- // leaves space for one more character. Some put_xxx() functions don't use
- // *nprintf() and could use that last character. In that case log line will
- // have multiple (two) half-written parts which is confusing. To workaround
- // that we allow *nprintf() to write its 0 in the eol area (which is always
- // not empty).
- return (size_t)(msg->e - msg->p + 1);
-}
-
-static INLINE void put_nprintf(transport_log_message *const msg, const int n) {
- if (0 < n) {
- msg->p = n < msg->e - msg->p ? msg->p + n : msg->e;
- }
-}
-
-static INLINE char *put_padding_r(const unsigned w, const char wc, char *p,
- char *e) {
- for (char *const b = e - w; b < p; *--p = wc) {
- }
- return p;
-}
-
-static char *put_integer_r(unsigned v, const int sign, const unsigned w,
- const char wc, char *const e) {
- static const char _signs[] = {'-', '0', '+'};
- static const char *const signs = _signs + 1;
- char *p = e;
- do {
- *--p = '0' + v % 10;
- } while (0 != (v /= 10));
- if (0 == sign) return put_padding_r(w, wc, p, e);
- if ('0' != wc) {
- *--p = signs[sign];
- return put_padding_r(w, wc, p, e);
- }
- p = put_padding_r(w, wc, p, e + 1);
- *--p = signs[sign];
- return p;
-}
-
-static INLINE char *put_uint_r(const unsigned v, const unsigned w,
- const char wc, char *const e) {
- return put_integer_r(v, 0, w, wc, e);
-}
-
-static INLINE char *put_int_r(const int v, const unsigned w, const char wc,
- char *const e) {
- return 0 <= v ? put_integer_r((unsigned)v, 0, w, wc, e)
- : put_integer_r((unsigned)-v, -1, w, wc, e);
-}
-
-static INLINE char *put_stringn(const char *const s_p, const char *const s_e,
- char *const p, char *const e) {
- const ptrdiff_t m = e - p;
- ptrdiff_t n = s_e - s_p;
- if (n > m) {
- n = m;
- }
- memcpy(p, s_p, n);
- return p + n;
-}
-
-static INLINE char *put_string(const char *s, char *p, char *const e) {
- const ptrdiff_t n = e - p;
- char *const c = (char *)memccpy(p, s, '\0', n);
- return 0 != c ? c - 1 : e;
-}
-
-static INLINE char *put_uint(unsigned v, const unsigned w, const char wc,
- char *const p, char *const e) {
- char buf[16];
- char *const se = buf + _countof(buf);
- char *sp = put_uint_r(v, w, wc, se);
- return put_stringn(sp, se, p, e);
-}
-
-#define PUT_CSTR_R(p, STR) \
- do { \
- for (unsigned i = sizeof(STR) - 1; 0 < i--;) { \
- *--(p) = (STR)[i]; \
- } \
- } \
- _TRANSPORT_LOG_ONCE
-
-#define PUT_CSTR_CHECKED(p, e, STR) \
- do { \
- for (unsigned i = 0; (e) > (p) && (sizeof(STR) - 1) > i; ++i) { \
- *(p)++ = (STR)[i]; \
- } \
- } \
- _TRANSPORT_LOG_ONCE
-
-/* F_INIT field support.
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__YEAR
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__MONTH
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__DAY
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__HOUR
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__MINUTE
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__SECOND
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__MILLISECOND
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__PID
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__TID
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__LEVEL
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__TAG(ps, ts)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__FUNCTION
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__FILENAME
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__FILELINE
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__S(s)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__F_INIT(expr) _PP_UNTUPLE(expr);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT__F_UINT(w, v)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_INIT(field) \
- _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT_, _, field)
-
-/* Implements generation of printf-like format string for log message
- * format specification.
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__ ""
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__YEAR "%04u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MONTH "%02u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__DAY "%02u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__HOUR "%02u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MINUTE "%02u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__SECOND "%02u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MILLISECOND "%03u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__PID "%5i"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__TID "%5i"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__LEVEL "%c"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__TAG UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FUNCTION "%s"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FILENAME "%s"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FILELINE "%u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__S(s) s
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__F_INIT(expr) ""
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT__F_UINT(w, v) "%" #w "u"
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT(field) \
- _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT_, _, field)
-
-/* Implements generation of printf-like format parameters for log message
- * format specification.
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__YEAR \
- , (unsigned)(tm.tm_year + 1900)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MONTH \
- , (unsigned)(tm.tm_mon + 1)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__DAY , (unsigned)tm.tm_mday
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__HOUR , (unsigned)tm.tm_hour
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MINUTE , (unsigned)tm.tm_min
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__SECOND , (unsigned)tm.tm_sec
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MILLISECOND , (unsigned)msec
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__PID , pid
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__TID , tid
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__LEVEL \
- , (char)lvl_char(msg->lvl)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__TAG UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FUNCTION , funcname(src->func)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FILENAME , filename(src->file)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FILELINE , src->line
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__S(s)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__F_INIT(expr)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL__F_UINT(w, v) , v
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL(field) \
- _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL_, _, field)
-
-/* Implements generation of put_xxx_t statements for log message specification.
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__YEAR \
- p = put_uint_r(tm.tm_year + 1900, 4, '0', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__MONTH \
- p = put_uint_r((unsigned)tm.tm_mon + 1, 2, '0', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__DAY \
- p = put_uint_r((unsigned)tm.tm_mday, 2, '0', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__HOUR \
- p = put_uint_r((unsigned)tm.tm_hour, 2, '0', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__MINUTE \
- p = put_uint_r((unsigned)tm.tm_min, 2, '0', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__SECOND \
- p = put_uint_r((unsigned)tm.tm_sec, 2, '0', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__MILLISECOND \
- p = put_uint_r(msec, 3, '0', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__PID p = put_int_r(pid, 5, ' ', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__TID p = put_int_r(tid, 5, ' ', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__LEVEL *--p = lvl_char(msg->lvl);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__TAG UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__FUNCTION UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__FILENAME UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__FILELINE UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__S(s) PUT_CSTR_R(p, s);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__F_INIT(expr)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R__F_UINT(w, v) \
- p = put_uint_r(v, w, ' ', p);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R(field) \
- _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R_, _, field)
-
-static void put_ctx(transport_log_message *const msg) {
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT, TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
- VAR_UNUSED(msg);
-#else
-#if _TRANSPORT_LOG_MESSAGE_FORMAT_DATETIME_USED
- struct tm tm;
- unsigned msec;
- g_time_cb(&tm, &msec);
-#endif
-#if _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS( \
- PID, TRANSPORT_LOG_MESSAGE_CTX_FORMAT) || \
- _TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(TID, \
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
- int pid, tid;
- g_pid_cb(&pid, &tid);
-#endif
-
-#if TRANSPORT_LOG_OPTIMIZE_SIZE
- int n;
- n = snprintf(msg->p, nprintf_size(msg),
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT,
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL,
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT));
- put_nprintf(msg, n);
-#else
- char buf[64];
- char *const e = buf + sizeof(buf);
- char *p = e;
- _PP_RMAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT_R,
- TRANSPORT_LOG_MESSAGE_CTX_FORMAT)
- msg->p = put_stringn(p, e, msg->p, msg->e);
-#endif
-#endif
-}
-
-#define PUT_TAG(msg, tag, prefix_delim, tag_delim) \
- do { \
- const char *ch; \
- msg->tag_b = msg->p; \
- if (0 != (ch = _transport_log_tag_prefix)) { \
- for (; msg->e != msg->p && 0 != (*msg->p = *ch); ++msg->p, ++ch) { \
- } \
- } \
- if (0 != (ch = tag) && 0 != tag[0]) { \
- if (msg->tag_b != msg->p) { \
- PUT_CSTR_CHECKED(msg->p, msg->e, prefix_delim); \
- } \
- for (; msg->e != msg->p && 0 != (*msg->p = *ch); ++msg->p, ++ch) { \
- } \
- } \
- msg->tag_e = msg->p; \
- if (msg->tag_b != msg->p) { \
- PUT_CSTR_CHECKED(msg->p, msg->e, tag_delim); \
- } \
- } \
- _TRANSPORT_LOG_ONCE
-
-/* Implements simple put statements for log message specification.
- */
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__YEAR UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__MONTH UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__DAY UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__HOUR UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__MINUTE UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__SECOND UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__MILLISECOND UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__PID UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__TID UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__LEVEL UNDEFINED
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__TAG(pd, td) \
- PUT_TAG(msg, tag, pd, td);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__FUNCTION \
- msg->p = put_string(funcname(src->func), msg->p, msg->e);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__FILENAME \
- msg->p = put_string(filename(src->file), msg->p, msg->e);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__FILELINE \
- msg->p = put_uint(src->line, 0, '\0', msg->p, msg->e);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__S(s) \
- PUT_CSTR_CHECKED(msg->p, msg->e, s);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__F_INIT(expr)
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT__F_UINT(w, v) \
- msg->p = put_uint(v, w, ' ', msg->p, msg->e);
-#define _TRANSPORT_LOG_MESSAGE_FORMAT_PUT(field) \
- _PP_CONCAT_3(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT_, _, field)
-
-static void put_tag(transport_log_message *const msg, const char *const tag) {
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT, TRANSPORT_LOG_MESSAGE_TAG_FORMAT)
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(TAG, \
- TRANSPORT_LOG_MESSAGE_TAG_FORMAT)
- VAR_UNUSED(tag);
-#endif
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(TRANSPORT_LOG_MESSAGE_TAG_FORMAT)
- VAR_UNUSED(msg);
-#else
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT, TRANSPORT_LOG_MESSAGE_TAG_FORMAT)
-#endif
-}
-
-static void put_src(transport_log_message *const msg,
- const src_location *const src) {
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_INIT, TRANSPORT_LOG_MESSAGE_SRC_FORMAT)
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS( \
- FUNCTION, TRANSPORT_LOG_MESSAGE_SRC_FORMAT) && \
- !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS( \
- FILENAME, TRANSPORT_LOG_MESSAGE_SRC_FORMAT) && \
- !_TRANSPORT_LOG_MESSAGE_FORMAT_CONTAINS(FILELINE, \
- TRANSPORT_LOG_MESSAGE_SRC_FORMAT)
- VAR_UNUSED(src);
-#endif
-#if !_TRANSPORT_LOG_MESSAGE_FORMAT_FIELDS(TRANSPORT_LOG_MESSAGE_SRC_FORMAT)
- VAR_UNUSED(msg);
-#else
-#if TRANSPORT_LOG_OPTIMIZE_SIZE
- int n;
- n = snprintf(msg->p, nprintf_size(msg),
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_FMT,
- TRANSPORT_LOG_MESSAGE_SRC_FORMAT)
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PRINTF_VAL,
- TRANSPORT_LOG_MESSAGE_SRC_FORMAT));
- put_nprintf(msg, n);
-#else
- _PP_MAP(_TRANSPORT_LOG_MESSAGE_FORMAT_PUT, TRANSPORT_LOG_MESSAGE_SRC_FORMAT)
-#endif
-#endif
-}
-
-static void put_msg(transport_log_message *const msg, const char *const fmt,
- va_list va) {
- int n;
- msg->msg_b = msg->p;
- n = vsnprintf(msg->p, nprintf_size(msg), fmt, va);
- put_nprintf(msg, n);
-}
-
-static void output_mem(const transport_log_spec *log,
- transport_log_message *const msg,
- const mem_block *const mem) {
- if (0 == mem->d || 0 == mem->d_sz) {
- return;
- }
- const unsigned char *mem_p = (const unsigned char *)mem->d;
- const unsigned char *const mem_e = mem_p + mem->d_sz;
- const unsigned char *mem_cut;
- const ptrdiff_t mem_width = (ptrdiff_t)log->format->mem_width;
- char *const hex_b = msg->msg_b;
- char *const ascii_b = hex_b + 2 * mem_width + 2;
- char *const ascii_e = ascii_b + mem_width;
- if (msg->e < ascii_e) {
- return;
- }
- while (mem_p != mem_e) {
- char *hex = hex_b;
- char *ascii = ascii_b;
- for (mem_cut = mem_width < mem_e - mem_p ? mem_p + mem_width : mem_e;
- mem_cut != mem_p; ++mem_p) {
- const unsigned char ch = *mem_p;
- *hex++ = c_hex[(0xf0 & ch) >> 4];
- *hex++ = c_hex[(0x0f & ch)];
- *ascii++ = isprint(ch) ? (char)ch : '?';
- }
- while (hex != ascii_b) {
- *hex++ = ' ';
- }
- msg->p = ascii;
- log->output->callback(msg, log->output->arg);
- }
-}
-
-void transport_log_set_tag_prefix(const char *const prefix) {
- _transport_log_tag_prefix = prefix;
-}
-
-void transport_log_set_mem_width(const unsigned w) {
- _transport_log_global_format.mem_width = w;
-}
-
-void transport_log_set_output_level(const int lvl) {
- _transport_log_global_output_lvl = lvl;
-}
-
-void transport_log_set_output_v(const unsigned mask, void *const arg,
- const transport_log_output_cb callback) {
- _transport_log_global_output.mask = mask;
- _transport_log_global_output.arg = arg;
- _transport_log_global_output.callback = callback;
-}
-
-static void _transport_log_write_imp(const transport_log_spec *log,
- const src_location *const src,
- const mem_block *const mem, const int lvl,
- const char *const tag,
- const char *const fmt, va_list va) {
- transport_log_message msg;
- char buf[TRANSPORT_LOG_BUF_SZ];
- const unsigned mask = log->output->mask;
- msg.lvl = lvl;
- msg.tag = tag;
- g_buffer_cb(&msg, buf);
- if (TRANSPORT_LOG_PUT_CTX & mask) {
- put_ctx(&msg);
- }
- if (TRANSPORT_LOG_PUT_TAG & mask) {
- put_tag(&msg, tag);
- }
- if (0 != src && TRANSPORT_LOG_PUT_SRC & mask) {
- put_src(&msg, src);
- }
- if (TRANSPORT_LOG_PUT_MSG & mask) {
- put_msg(&msg, fmt, va);
- }
- log->output->callback(&msg, log->output->arg);
- if (0 != mem && TRANSPORT_LOG_PUT_MSG & mask) {
- output_mem(log, &msg, mem);
- }
-}
-
-void _transport_log_write_d(const char *const func, const char *const file,
- const unsigned line, const int lvl,
- const char *const tag, const char *const fmt, ...) {
- const src_location src = {func, file, line};
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(&global_spec, &src, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _transport_log_write_aux_d(const char *const func, const char *const file,
- const unsigned line,
- const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const char *const fmt, ...) {
- const src_location src = {func, file, line};
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(log, &src, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _transport_log_write(const int lvl, const char *const tag,
- const char *const fmt, ...) {
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(&global_spec, 0, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _transport_log_write_aux(const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const char *const fmt, ...) {
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(log, 0, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _transport_log_write_mem_d(const char *const func, const char *const file,
- const unsigned line, const int lvl,
- const char *const tag, const void *const d,
- const unsigned d_sz, const char *const fmt,
- ...) {
- const src_location src = {func, file, line};
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(&global_spec, &src, &mem, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _transport_log_write_mem_aux_d(const char *const func,
- const char *const file, const unsigned line,
- const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...) {
- const src_location src = {func, file, line};
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(log, &src, &mem, lvl, tag, fmt, va);
- va_end(va);
-}
+constexpr char LogConfiguration::log_config_section[];
+constexpr char LogConfiguration::log_name[];
-void _transport_log_write_mem(const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...) {
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(&global_spec, 0, &mem, lvl, tag, fmt, va);
- va_end(va);
-}
+LogConfiguration log_conf = LogConfiguration();
-void _transport_log_write_mem_aux(const transport_log_spec *const log,
- const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...) {
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _transport_log_write_imp(log, 0, &mem, lvl, tag, fmt, va);
- va_end(va);
-} \ No newline at end of file
+} // namespace utils
diff --git a/libtransport/src/utils/min_filter.h b/libtransport/src/utils/min_filter.h
index f1aaea7a8..092555ce0 100644
--- a/libtransport/src/utils/min_filter.h
+++ b/libtransport/src/utils/min_filter.h
@@ -15,9 +15,6 @@
#pragma once
-#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/utils/log.h>
-
#include <deque>
#include <iostream>
#include <set>
@@ -34,7 +31,7 @@ class MinFilter {
std::size_t size() { return by_arrival_.size(); }
template <typename R>
- TRANSPORT_ALWAYS_INLINE void pushBack(R&& value) {
+ void pushBack(R&& value) {
if (by_arrival_.size() >= size_) {
by_order_.erase(by_arrival_.back());
by_arrival_.pop_back();
@@ -43,14 +40,14 @@ class MinFilter {
by_arrival_.push_front(by_order_.insert(std::forward<R>(value)));
}
- TRANSPORT_ALWAYS_INLINE void clear() {
+ void clear() {
by_arrival_.clear();
by_order_.clear();
}
- TRANSPORT_ALWAYS_INLINE const T& begin() { return *by_order_.cbegin(); }
+ const T& begin() { return *by_order_.cbegin(); }
- TRANSPORT_ALWAYS_INLINE const T& rBegin() { return *by_order_.crbegin(); }
+ const T& rBegin() { return *by_order_.crbegin(); }
private:
std::multiset<T> by_order_;
diff --git a/libtransport/src/utils/suffix_strategy.h b/libtransport/src/utils/suffix_strategy.h
index 6c4dd2785..ee016308e 100644
--- a/libtransport/src/utils/suffix_strategy.h
+++ b/libtransport/src/utils/suffix_strategy.h
@@ -33,6 +33,8 @@ class SuffixStrategy {
virtual ~SuffixStrategy() = default;
+ virtual uint32_t checkNextSuffix() = 0;
+
virtual uint32_t getNextSuffix() = 0;
virtual uint32_t getFinalSuffix() { return final_suffix_; }
@@ -43,8 +45,12 @@ class SuffixStrategy {
}
}
+ virtual uint32_t checkNextManifestSuffix() = 0;
+
virtual uint32_t getNextManifestSuffix() = 0;
+ virtual uint32_t checkNextContentSuffix() = 0;
+
virtual uint32_t getNextContentSuffix() = 0;
virtual void reset(uint32_t offset = 0) = 0;
@@ -74,15 +80,27 @@ class IncrementalSuffixStrategy : public SuffixStrategy {
: SuffixStrategy(NextSegmentCalculationStrategy::INCREMENTAL),
next_suffix_(start_offset) {}
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextSuffix() override {
+ return next_suffix_;
+ }
+
TRANSPORT_ALWAYS_INLINE std::uint32_t getNextSuffix() override {
incrementTotalCount();
return next_suffix_++;
}
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextContentSuffix() override {
+ return checkNextSuffix();
+ }
+
TRANSPORT_ALWAYS_INLINE std::uint32_t getNextContentSuffix() override {
return getNextSuffix();
}
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextManifestSuffix() override {
+ return checkNextSuffix();
+ }
+
TRANSPORT_ALWAYS_INLINE std::uint32_t getNextManifestSuffix() override {
return getNextSuffix();
}
@@ -112,17 +130,30 @@ class CapacityBasedSuffixStrategy : public SuffixStrategy {
segments_in_manifest_(manifest_capacity),
current_manifest_iteration_(0) {}
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextSuffix() override {
+ return next_suffix_;
+ }
+
TRANSPORT_ALWAYS_INLINE std::uint32_t getNextSuffix() override {
incrementTotalCount();
return next_suffix_++;
}
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextContentSuffix() override {
+ return next_suffix_ % segments_in_manifest_ == 0 ? next_suffix_
+ : (next_suffix_ + 1);
+ }
+
TRANSPORT_ALWAYS_INLINE std::uint32_t getNextContentSuffix() override {
incrementTotalCount();
return next_suffix_ % segments_in_manifest_ == 0 ? next_suffix_++
: ++next_suffix_;
}
+ TRANSPORT_ALWAYS_INLINE std::uint32_t checkNextManifestSuffix() override {
+ return (current_manifest_iteration_ + 1) * (segments_in_manifest_ + 1);
+ }
+
TRANSPORT_ALWAYS_INLINE std::uint32_t getNextManifestSuffix() override {
incrementTotalCount();
return (current_manifest_iteration_++) * (segments_in_manifest_ + 1);
diff --git a/libtransport/third-party/CMakeLists.txt b/libtransport/third-party/CMakeLists.txt
new file mode 100644
index 000000000..46a4c0f23
--- /dev/null
+++ b/libtransport/third-party/CMakeLists.txt
@@ -0,0 +1,83 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+include(FetchContent)
+
+set (THIRD_PARTY_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})
+
+option(ENABLE_RELY "Enable download/build of rely library" OFF)
+
+if (ENABLE_RELY)
+ ##################################
+ # Download librely
+
+ if(DEFINED ENV{BITBUCKET_USERNAME} AND DEFINED ENV{BITBUCKET_PASSWORD})
+ set(GIT_REPO https://$ENV{BITBUCKET_USERNAME}:$ENV{BITBUCKET_PASSWORD}@bitbucket-eng-gpk1.cisco.com/bitbucket/scm/icn/rely.git)
+ else()
+ set(GIT_REPO ssh://git@bitbucket-eng-gpk1.cisco.com:7999/icn/rely.git)
+ endif()
+
+ FetchContent_Declare(
+ rely
+ GIT_REPOSITORY ${GIT_REPO}
+ GIT_TAG release/latest
+ )
+
+ set(ENABLE_PIC ON)
+ FetchContent_MakeAvailable(rely)
+
+ list(APPEND THIRD_PARTY_INCLUDE_DIRS
+ ${rely_BINARY_DIR}
+ ${rely_SOURCE_DIR}/src
+ )
+
+ # Get rely libraries
+ get_property(steinwurf_object_libraries GLOBAL
+ PROPERTY steinwurf::object_libraries)
+
+ foreach(rely_library ${steinwurf_object_libraries})
+ list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
+ $<TARGET_OBJECTS:${rely_library}>
+ )
+ endforeach()
+
+ list(APPEND THIRD_PARTY_DEPENDENCIES
+ rely
+ )
+endif()
+
+FetchContent_Declare(
+ glog
+ URL https://github.com/google/glog/archive/refs/tags/v0.5.0.zip
+ PATCH_COMMAND patch -p1 CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/glog.patch
+)
+
+FetchContent_MakeAvailable(glog)
+
+list(APPEND THIRD_PARTY_INCLUDE_DIRS
+ ${glog_BINARY_DIR}
+ ${glog_SOURCE_DIR}/src
+)
+
+list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
+ $<TARGET_OBJECTS:glog>
+)
+
+list(APPEND THIRD_PARTY_DEPENDENCIES
+ glog
+)
+
+set (THIRD_PARTY_LIBRARIES ${THIRD_PARTY_LIBRARIES} PARENT_SCOPE)
+set (THIRD_PARTY_OBJECT_LIBRARIES ${THIRD_PARTY_OBJECT_LIBRARIES} PARENT_SCOPE)
+set (THIRD_PARTY_INCLUDE_DIRS ${THIRD_PARTY_INCLUDE_DIRS} PARENT_SCOPE)
+set (THIRD_PARTY_DEPENDENCIES ${THIRD_PARTY_DEPENDENCIES} PARENT_SCOPE)
diff --git a/libtransport/third-party/CMakeLists.txt.orig b/libtransport/third-party/CMakeLists.txt.orig
new file mode 100644
index 000000000..84db8cb4c
--- /dev/null
+++ b/libtransport/third-party/CMakeLists.txt.orig
@@ -0,0 +1,85 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+include(FetchContent)
+
+set (THIRD_PARTY_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})
+
+option(ENABLE_RELY "Enable download/build of rely library" OFF)
+
+if (ENABLE_RELY)
+ ##################################
+ # Download librely
+
+ if(DEFINED ENV{BITBUCKET_USERNAME} AND DEFINED ENV{BITBUCKET_PASSWORD})
+ set(GIT_REPO https://$ENV{BITBUCKET_USERNAME}:$ENV{BITBUCKET_PASSWORD}@bitbucket-eng-gpk1.cisco.com/bitbucket/scm/icn/rely.git)
+ else()
+ set(GIT_REPO ssh://git@bitbucket-eng-gpk1.cisco.com:7999/icn/rely.git)
+ endif()
+
+ FetchContent_Declare(
+ rely
+ GIT_REPOSITORY ${GIT_REPO}
+ GIT_TAG release/latest
+ FETCHCONTENT_QUIET
+ )
+
+ set(ENABLE_PIC ON)
+ FetchContent_MakeAvailable(rely)
+
+ list(APPEND THIRD_PARTY_INCLUDE_DIRS
+ ${rely_BINARY_DIR}
+ ${rely_SOURCE_DIR}/src
+ )
+
+ # Get rely libraries
+ get_property(steinwurf_object_libraries GLOBAL
+ PROPERTY steinwurf::object_libraries)
+
+ foreach(rely_library ${steinwurf_object_libraries})
+ list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
+ $<TARGET_OBJECTS:${rely_library}>
+ )
+ endforeach()
+
+ list(APPEND THIRD_PARTY_DEPENDENCIES
+ rely
+ )
+endif()
+
+FetchContent_Declare(
+ glog
+ URL https://github.com/google/glog/archive/refs/tags/v0.5.0.zip
+ PATCH_COMMAND patch -p1 CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/glog.patch
+ FETCHCONTENT_QUIET
+)
+
+FetchContent_MakeAvailable(glog)
+
+list(APPEND THIRD_PARTY_INCLUDE_DIRS
+ ${glog_BINARY_DIR}
+ ${glog_SOURCE_DIR}/src
+)
+
+list(APPEND THIRD_PARTY_OBJECT_LIBRARIES
+ $<TARGET_OBJECTS:glog>
+)
+
+list(APPEND THIRD_PARTY_DEPENDENCIES
+ glog
+)
+
+set (THIRD_PARTY_LIBRARIES ${THIRD_PARTY_LIBRARIES} PARENT_SCOPE)
+set (THIRD_PARTY_OBJECT_LIBRARIES ${THIRD_PARTY_OBJECT_LIBRARIES} PARENT_SCOPE)
+set (THIRD_PARTY_INCLUDE_DIRS ${THIRD_PARTY_INCLUDE_DIRS} PARENT_SCOPE)
+set (THIRD_PARTY_DEPENDENCIES ${THIRD_PARTY_DEPENDENCIES} PARENT_SCOPE)
diff --git a/libtransport/third-party/CMakeLists.txt.rej b/libtransport/third-party/CMakeLists.txt.rej
new file mode 100644
index 000000000..4ebaf9061
--- /dev/null
+++ b/libtransport/third-party/CMakeLists.txt.rej
@@ -0,0 +1,21 @@
+--- CMakeLists.txt
++++ CMakeLists.txt
+@@ -41,9 +41,6 @@ if (NOT WITH_THREADS)
+ set (CMAKE_DISABLE_FIND_PACKAGE_Threads ON)
+ endif (NOT WITH_THREADS)
+
+-set (CMAKE_C_VISIBILITY_PRESET hidden)
+-set (CMAKE_CXX_VISIBILITY_PRESET hidden)
+-set (CMAKE_VISIBILITY_INLINES_HIDDEN 1)
+ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
+ include (CheckCXXSourceCompiles)
+@@ -570,7 +567,7 @@ if (_glog_CMake_MODULES)
+ )
+ endif (_glog_CMake_MODULES)
+
+-add_library (glog
++add_library (glog OBJECT
+ ${GLOG_SRCS}
+ ${_glog_BINARY_CMake_MODULES}
+ )
diff --git a/libtransport/third-party/glog.patch b/libtransport/third-party/glog.patch
new file mode 100644
index 000000000..9d6e46df0
--- /dev/null
+++ b/libtransport/third-party/glog.patch
@@ -0,0 +1,23 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 62ebbcc..7d92fa5 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -41,9 +41,6 @@ if (NOT WITH_THREADS)
+ set (CMAKE_DISABLE_FIND_PACKAGE_Threads ON)
+ endif (NOT WITH_THREADS)
+
+-set (CMAKE_C_VISIBILITY_PRESET hidden)
+-set (CMAKE_CXX_VISIBILITY_PRESET hidden)
+-set (CMAKE_VISIBILITY_INLINES_HIDDEN 1)
+ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
+ include (CheckCXXSourceCompiles)
+@@ -570,7 +567,7 @@ if (_glog_CMake_MODULES)
+ )
+ endif (_glog_CMake_MODULES)
+
+-add_library (glog
++add_library (glog OBJECT
+ ${GLOG_SRCS}
+ ${_glog_BINARY_CMake_MODULES}
+ )
diff --git a/telemetry/CMakeLists.txt b/telemetry/CMakeLists.txt
index 53fd04f01..fbb929529 100644
--- a/telemetry/CMakeLists.txt
+++ b/telemetry/CMakeLists.txt
@@ -12,7 +12,7 @@
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
if ((CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) OR
(BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
diff --git a/telemetry/vpp-collectd/CMakeLists.txt b/telemetry/vpp-collectd/CMakeLists.txt
index 8f82745f2..7afb3f432 100644
--- a/telemetry/vpp-collectd/CMakeLists.txt
+++ b/telemetry/vpp-collectd/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
set(COLLECTD_PLUGINS hicn-collectd-plugins)
project(hicn-collectd-plugins)
diff --git a/telemetry/vpp-collectd/cmake/Modules/Packaging.cmake b/telemetry/vpp-collectd/cmake/Modules/Packaging.cmake
index dc4629a26..72da05d02 100644
--- a/telemetry/vpp-collectd/cmake/Modules/Packaging.cmake
+++ b/telemetry/vpp-collectd/cmake/Modules/Packaging.cmake
@@ -16,7 +16,7 @@
######################
set(${COLLECTD_PLUGINS}_DESCRIPTION
- "A high-performance Hybrid ICN forwarder as a plugin to VPP."
+ "VPP and hICN plugins for collectd"
CACHE STRING "Description for deb/rpm package."
)
diff --git a/telemetry/vpp-collectd/common/README.md b/telemetry/vpp-collectd/common/README.md
new file mode 100644
index 000000000..e3b9c74f6
--- /dev/null
+++ b/telemetry/vpp-collectd/common/README.md
@@ -0,0 +1,12 @@
+# Headers for collectd plugins
+
+These headers are required for plugin development but are not shipped with the
+`collectd` Ubuntu 20.04 package (as of May 2021):
+
+* [common.h](https://github.com/collectd/collectd/blob/main/src/utils/common/common.h)
+* [plugin.h](https://github.com/collectd/collectd/blob/main/src/daemon/plugin.h)
+* [meta_data.h](https://github.com/collectd/collectd/blob/main/src/utils/metadata/meta_data.h)
+
+Related issues:
+* [GitHub](https://github.com/collectd/collectd/issues/3881)
+* [Ubuntu](https://bugs.launchpad.net/ubuntu/+source/collectd/+bug/1929079)
diff --git a/telemetry/vpp-collectd/common/common.h b/telemetry/vpp-collectd/common/common.h
new file mode 100644
index 000000000..fce2d12bb
--- /dev/null
+++ b/telemetry/vpp-collectd/common/common.h
@@ -0,0 +1,405 @@
+/**
+ * collectd - src/common.h
+ * Copyright (C) 2005-2014 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ * Niki W. Waibel <niki.waibel@gmx.net>
+ **/
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "collectd.h"
+
+#include "plugin.h"
+
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#define sfree(ptr) \
+ do { \
+ free(ptr); \
+ (ptr) = NULL; \
+ } while (0)
+
+#define STATIC_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+#define IS_TRUE(s) \
+ ((strcasecmp("true", (s)) == 0) || (strcasecmp("yes", (s)) == 0) || \
+ (strcasecmp("on", (s)) == 0))
+#define IS_FALSE(s) \
+ ((strcasecmp("false", (s)) == 0) || (strcasecmp("no", (s)) == 0) || \
+ (strcasecmp("off", (s)) == 0))
+
+struct rate_to_value_state_s {
+ value_t last_value;
+ cdtime_t last_time;
+ gauge_t residual;
+};
+typedef struct rate_to_value_state_s rate_to_value_state_t;
+
+struct value_to_rate_state_s {
+ value_t last_value;
+ cdtime_t last_time;
+};
+typedef struct value_to_rate_state_s value_to_rate_state_t;
+
+char *sstrncpy(char *dest, const char *src, size_t n);
+
+__attribute__((format(printf, 3, 4))) int ssnprintf(char *str, size_t size,
+ char const *format, ...);
+
+__attribute__((format(printf, 1, 2))) char *ssnprintf_alloc(char const *format,
+ ...);
+
+char *sstrdup(const char *s);
+size_t sstrnlen(const char *s, size_t n);
+char *sstrndup(const char *s, size_t n);
+void *smalloc(size_t size);
+char *sstrerror(int errnum, char *buf, size_t buflen);
+
+#ifndef ERRBUF_SIZE
+#define ERRBUF_SIZE 256
+#endif
+
+#define STRERROR(e) sstrerror((e), (char[ERRBUF_SIZE]){0}, ERRBUF_SIZE)
+#define STRERRNO STRERROR(errno)
+
+/*
+ * NAME
+ * sread
+ *
+ * DESCRIPTION
+ * Reads exactly `n' bytes or fails. Syntax and other behavior is analogous
+ * to `read(2)'.
+ *
+ * PARAMETERS
+ * `fd' File descriptor to write to.
+ * `buf' Buffer that is to be written.
+ * `count' Number of bytes in the buffer.
+ *
+ * RETURN VALUE
+ * Zero upon success or non-zero if an error occurred. `errno' is set in this
+ * case.
+ */
+int sread(int fd, void *buf, size_t count);
+
+/*
+ * NAME
+ * swrite
+ *
+ * DESCRIPTION
+ * Writes exactly `n' bytes or fails. Syntax and other behavior is analogous
+ * to `write(2)'.
+ *
+ * PARAMETERS
+ * `fd' File descriptor to write to.
+ * `buf' Buffer that is to be written.
+ * `count' Number of bytes in the buffer.
+ *
+ * RETURN VALUE
+ * Zero upon success or non-zero if an error occurred. `errno' is set in this
+ * case.
+ */
+int swrite(int fd, const void *buf, size_t count);
+
+/*
+ * NAME
+ * strsplit
+ *
+ * DESCRIPTION
+ * Splits a string into parts and stores pointers to the parts in `fields'.
+ * The characters split at are: " ", "\t", "\r", and "\n".
+ *
+ * PARAMETERS
+ * `string' String to split. This string will be modified. `fields' will
+ * contain pointers to parts of this string, so free'ing it
+ * will destroy `fields' as well.
+ * `fields' Array of strings where pointers to the parts will be stored.
+ * `size' Number of elements in the array. No more than `size'
+ * pointers will be stored in `fields'.
+ *
+ * RETURN VALUE
+ * Returns the number of parts stored in `fields'.
+ */
+int strsplit(char *string, char **fields, size_t size);
+
+/*
+ * NAME
+ * strjoin
+ *
+ * DESCRIPTION
+ * Joins together several parts of a string using `sep' as a separator. This
+ * is equivalent to the Perl built-in `join'.
+ *
+ * PARAMETERS
+ * `dst' Buffer where the result is stored. Can be NULL if you need to
+ * determine the required buffer size only.
+ * `dst_len' Length of the destination buffer. No more than this many
+ * bytes will be written to the memory pointed to by `dst',
+ * including the trailing null-byte. Must be zero if dst is
+ * NULL.
+ * `fields' Array of strings to be joined.
+ * `fields_num' Number of elements in the `fields' array.
+ * `sep' String to be inserted between any two elements of `fields'.
+ * This string is neither prepended nor appended to the result.
+ * Instead of passing "" (empty string) one can pass NULL.
+ *
+ * RETURN VALUE
+ * Returns the number of characters in the resulting string, excluding a
+ * tailing null byte. If this value is greater than or equal to "dst_len", the
+ * result in "dst" is truncated (but still null terminated). On error a
+ * negative value is returned.
+ */
+int strjoin(char *dst, size_t dst_len, char **fields, size_t fields_num,
+ const char *sep);
+
+/*
+ * NAME
+ * escape_slashes
+ *
+ * DESCRIPTION
+ * Removes slashes ("/") from "buffer". If buffer contains a single slash,
+ * the result will be "root". Leading slashes are removed. All other slashes
+ * are replaced with underscores ("_").
+ * This function is used by plugin_dispatch_values() to escape all parts of
+ * the identifier.
+ *
+ * PARAMETERS
+ * `buffer' String to be escaped.
+ * `buffer_size' Size of the buffer. No more then this many bytes will be
+ * written to `buffer', including the trailing null-byte.
+ *
+ * RETURN VALUE
+ * Returns zero upon success and a value smaller than zero upon failure.
+ */
+int escape_slashes(char *buffer, size_t buffer_size);
+
+/**
+ * NAME
+ * escape_string
+ *
+ * DESCRIPTION
+ * escape_string quotes and escapes a string to be usable with collectd's
+ * plain text protocol. "simple" strings are left as they are, for example if
+ * buffer is 'simple' before the call, it will remain 'simple'. However, if
+ * buffer contains 'more "complex"' before the call, the returned buffer will
+ * contain '"more \"complex\""'.
+ *
+ * If the buffer is too small to contain the escaped string, the string will
+ * be truncated. However, leading and trailing double quotes, as well as an
+ * ending null byte are guaranteed.
+ *
+ * RETURN VALUE
+ * Returns zero on success, even if the string was truncated. Non-zero on
+ * failure.
+ */
+int escape_string(char *buffer, size_t buffer_size);
+
+/*
+ * NAME
+ * replace_special
+ *
+ * DESCRIPTION
+ * Replaces any special characters (anything that's not alpha-numeric or a
+ * dash) with an underscore.
+ *
+ * E.g. "foo$bar&" would become "foo_bar_".
+ *
+ * PARAMETERS
+ * `buffer' String to be handled.
+ * `buffer_size' Length of the string. The function returns after
+ * encountering a null-byte or reading this many bytes.
+ */
+void replace_special(char *buffer, size_t buffer_size);
+
+/*
+ * NAME
+ * strunescape
+ *
+ * DESCRIPTION
+ * Replaces any escaped characters in a string with the appropriate special
+ * characters. The following escaped characters are recognized:
+ *
+ * \t -> <tab>
+ * \n -> <newline>
+ * \r -> <carriage return>
+ *
+ * For all other escacped characters only the backslash will be removed.
+ *
+ * PARAMETERS
+ * `buf' String to be unescaped.
+ * `buf_len' Length of the string, including the terminating null-byte.
+ *
+ * RETURN VALUE
+ * Returns zero upon success, a value less than zero else.
+ */
+int strunescape(char *buf, size_t buf_len);
+
+/**
+ * Removed trailing newline characters (CR and LF) from buffer, which must be
+ * null terminated. Returns the length of the resulting string.
+ */
+__attribute__((nonnull(1))) size_t strstripnewline(char *buffer);
+
+/*
+ * NAME
+ * timeval_cmp
+ *
+ * DESCRIPTION
+ * Compare the two time values `tv0' and `tv1' and store the absolut value
+ * of the difference in the time value pointed to by `delta' if it does not
+ * equal NULL.
+ *
+ * RETURN VALUE
+ * Returns an integer less than, equal to, or greater than zero if `tv0' is
+ * less than, equal to, or greater than `tv1' respectively.
+ */
+int timeval_cmp(struct timeval tv0, struct timeval tv1, struct timeval *delta);
+
+/* make sure tv_usec stores less than a second */
+#define NORMALIZE_TIMEVAL(tv) \
+ do { \
+ (tv).tv_sec += (tv).tv_usec / 1000000; \
+ (tv).tv_usec = (tv).tv_usec % 1000000; \
+ } while (0)
+
+/* make sure tv_sec stores less than a second */
+#define NORMALIZE_TIMESPEC(tv) \
+ do { \
+ (tv).tv_sec += (tv).tv_nsec / 1000000000; \
+ (tv).tv_nsec = (tv).tv_nsec % 1000000000; \
+ } while (0)
+
+int check_create_dir(const char *file_orig);
+
+#ifdef HAVE_LIBKSTAT
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+int get_kstat(kstat_t **ksp_ptr, char *module, int instance, char *name);
+long long get_kstat_value(kstat_t *ksp, char *name);
+#endif
+
+#ifndef HAVE_HTONLL
+unsigned long long ntohll(unsigned long long n);
+unsigned long long htonll(unsigned long long n);
+#endif
+
+#if FP_LAYOUT_NEED_NOTHING
+#define ntohd(d) (d)
+#define htond(d) (d)
+#elif FP_LAYOUT_NEED_ENDIANFLIP || FP_LAYOUT_NEED_INTSWAP
+double ntohd(double d);
+double htond(double d);
+#else
+#error \
+ "Don't know how to convert between host and network representation of doubles."
+#endif
+
+int format_name(char *ret, int ret_len, const char *hostname,
+ const char *plugin, const char *plugin_instance,
+ const char *type, const char *type_instance);
+#define FORMAT_VL(ret, ret_len, vl) \
+ format_name(ret, ret_len, (vl)->host, (vl)->plugin, (vl)->plugin_instance, \
+ (vl)->type, (vl)->type_instance)
+int format_values(char *ret, size_t ret_len, const data_set_t *ds,
+ const value_list_t *vl, bool store_rates);
+
+int parse_identifier(char *str, char **ret_host, char **ret_plugin,
+ char **ret_plugin_instance, char **ret_type,
+ char **ret_type_instance, char *default_host);
+int parse_identifier_vl(const char *str, value_list_t *vl);
+int parse_value(const char *value, value_t *ret_value, int ds_type);
+int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds);
+
+/* parse_value_file reads "path" and parses its content as an integer or
+ * floating point, depending on "ds_type". On success, the value is stored in
+ * "ret_value" and zero is returned. On failure, a non-zero value is returned.
+ */
+int parse_value_file(char const *path, value_t *ret_value, int ds_type);
+
+#if !HAVE_GETPWNAM_R
+struct passwd;
+int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen,
+ struct passwd **pwbufp);
+#endif
+
+int notification_init(notification_t *n, int severity, const char *message,
+ const char *host, const char *plugin,
+ const char *plugin_instance, const char *type,
+ const char *type_instance);
+#define NOTIFICATION_INIT_VL(n, vl) \
+ notification_init(n, NOTIF_FAILURE, NULL, (vl)->host, (vl)->plugin, \
+ (vl)->plugin_instance, (vl)->type, (vl)->type_instance)
+
+typedef int (*dirwalk_callback_f)(const char *dirname, const char *filename,
+ void *user_data);
+int walk_directory(const char *dir, dirwalk_callback_f callback,
+ void *user_data, int hidden);
+/* Returns the number of bytes read or negative on error. */
+ssize_t read_file_contents(char const *filename, void *buf, size_t bufsize);
+/* Writes the contents of the file into the buffer with a trailing NUL.
+ * Returns the number of bytes written to the buffer or negative on error. */
+ssize_t read_text_file_contents(char const *filename, char *buf,
+ size_t bufsize);
+
+counter_t counter_diff(counter_t old_value, counter_t new_value);
+
+/* Convert a rate back to a value_t. When converting to a derive_t, counter_t
+ * or absolute_t, take fractional residuals into account. This is important
+ * when scaling counters, for example.
+ * Returns zero on success. Returns EAGAIN when called for the first time; in
+ * this case the value_t is invalid and the next call should succeed. Other
+ * return values indicate an error. */
+int rate_to_value(value_t *ret_value, gauge_t rate,
+ rate_to_value_state_t *state, int ds_type, cdtime_t t);
+
+int value_to_rate(gauge_t *ret_rate, value_t value, int ds_type, cdtime_t t,
+ value_to_rate_state_t *state);
+
+/* Converts a service name (a string) to a port number
+ * (in the range [1-65535]). Returns less than zero on error. */
+int service_name_to_port_number(const char *service_name);
+
+/* Sets various, non-default, socket options */
+void set_sock_opts(int sockfd);
+
+/** Parse a string to a derive_t value. Returns zero on success or non-zero on
+ * failure. If failure is returned, ret_value is not touched. */
+int strtoderive(const char *string, derive_t *ret_value);
+
+/** Parse a string to a gauge_t value. Returns zero on success or non-zero on
+ * failure. If failure is returned, ret_value is not touched. */
+int strtogauge(const char *string, gauge_t *ret_value);
+
+int strarray_add(char ***ret_array, size_t *ret_array_len, char const *str);
+void strarray_free(char **array, size_t array_len);
+
+/** Check if the current process benefits from the capability passed in
+ * argument. Returns zero if it does, less than zero if it doesn't or on error.
+ * See capabilities(7) for the list of possible capabilities.
+ * */
+int check_capability(int arg);
+
+#endif /* COMMON_H */
diff --git a/telemetry/vpp-collectd/common/meta_data.h b/telemetry/vpp-collectd/common/meta_data.h
new file mode 100644
index 000000000..203b14607
--- /dev/null
+++ b/telemetry/vpp-collectd/common/meta_data.h
@@ -0,0 +1,71 @@
+/**
+ * collectd - src/meta_data.h
+ * Copyright (C) 2008-2011 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef META_DATA_H
+#define META_DATA_H
+
+#include "collectd.h"
+
+/*
+ * Defines
+ */
+#define MD_TYPE_STRING 1
+#define MD_TYPE_SIGNED_INT 2
+#define MD_TYPE_UNSIGNED_INT 3
+#define MD_TYPE_DOUBLE 4
+#define MD_TYPE_BOOLEAN 5
+
+struct meta_data_s;
+typedef struct meta_data_s meta_data_t;
+
+meta_data_t *meta_data_create(void);
+meta_data_t *meta_data_clone(meta_data_t *orig);
+int meta_data_clone_merge(meta_data_t **dest, meta_data_t *orig);
+void meta_data_destroy(meta_data_t *md);
+
+int meta_data_exists(meta_data_t *md, const char *key);
+int meta_data_type(meta_data_t *md, const char *key);
+int meta_data_toc(meta_data_t *md, char ***toc);
+int meta_data_delete(meta_data_t *md, const char *key);
+
+int meta_data_add_string(meta_data_t *md, const char *key, const char *value);
+int meta_data_add_signed_int(meta_data_t *md, const char *key, int64_t value);
+int meta_data_add_unsigned_int(meta_data_t *md, const char *key,
+ uint64_t value);
+int meta_data_add_double(meta_data_t *md, const char *key, double value);
+int meta_data_add_boolean(meta_data_t *md, const char *key, bool value);
+
+int meta_data_get_string(meta_data_t *md, const char *key, char **value);
+int meta_data_get_signed_int(meta_data_t *md, const char *key, int64_t *value);
+int meta_data_get_unsigned_int(meta_data_t *md, const char *key,
+ uint64_t *value);
+int meta_data_get_double(meta_data_t *md, const char *key, double *value);
+int meta_data_get_boolean(meta_data_t *md, const char *key, bool *value);
+
+/* Returns the value as a string, regardless of the type. */
+int meta_data_as_string(meta_data_t *md, const char *key, char **value);
+
+#endif /* META_DATA_H */
diff --git a/telemetry/vpp-collectd/common/plugin.h b/telemetry/vpp-collectd/common/plugin.h
new file mode 100644
index 000000000..0e75adc9b
--- /dev/null
+++ b/telemetry/vpp-collectd/common/plugin.h
@@ -0,0 +1,485 @@
+/**
+ * collectd - src/daemon/plugin.h
+ * Copyright (C) 2005-2014 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ * Sebastian Harl <sh at tokkee.org>
+ **/
+
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include "collectd.h"
+
+#include "configfile.h"
+#include "meta_data.h"
+#include "utils_time.h"
+
+#include <inttypes.h>
+#include <pthread.h>
+
+#define DS_TYPE_COUNTER 0
+#define DS_TYPE_GAUGE 1
+#define DS_TYPE_DERIVE 2
+#define DS_TYPE_ABSOLUTE 3
+
+#define DS_TYPE_TO_STRING(t) \
+ (t == DS_TYPE_COUNTER) \
+ ? "counter" \
+ : (t == DS_TYPE_GAUGE) \
+ ? "gauge" \
+ : (t == DS_TYPE_DERIVE) \
+ ? "derive" \
+ : (t == DS_TYPE_ABSOLUTE) ? "absolute" : "unknown"
+
+#ifndef LOG_ERR
+#define LOG_ERR 3
+#endif
+#ifndef LOG_WARNING
+#define LOG_WARNING 4
+#endif
+#ifndef LOG_NOTICE
+#define LOG_NOTICE 5
+#endif
+#ifndef LOG_INFO
+#define LOG_INFO 6
+#endif
+#ifndef LOG_DEBUG
+#define LOG_DEBUG 7
+#endif
+
+#define NOTIF_MAX_MSG_LEN 256
+
+#define NOTIF_FAILURE 1
+#define NOTIF_WARNING 2
+#define NOTIF_OKAY 4
+
+#define plugin_interval (plugin_get_ctx().interval)
+
+/*
+ * Public data types
+ */
+struct identifier_s {
+ char *host;
+ char *plugin;
+ char *plugin_instance;
+ char *type;
+ char *type_instance;
+};
+typedef struct identifier_s identifier_t;
+
+typedef unsigned long long counter_t;
+typedef double gauge_t;
+typedef int64_t derive_t;
+typedef uint64_t absolute_t;
+
+union value_u {
+ counter_t counter;
+ gauge_t gauge;
+ derive_t derive;
+ absolute_t absolute;
+};
+typedef union value_u value_t;
+
+struct value_list_s {
+ value_t *values;
+ size_t values_len;
+ cdtime_t time;
+ cdtime_t interval;
+ char host[DATA_MAX_NAME_LEN];
+ char plugin[DATA_MAX_NAME_LEN];
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ char type[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
+ meta_data_t *meta;
+};
+typedef struct value_list_s value_list_t;
+
+#define VALUE_LIST_INIT \
+ { .values = NULL, .meta = NULL }
+
+struct data_source_s {
+ char name[DATA_MAX_NAME_LEN];
+ int type;
+ double min;
+ double max;
+};
+typedef struct data_source_s data_source_t;
+
+struct data_set_s {
+ char type[DATA_MAX_NAME_LEN];
+ size_t ds_num;
+ data_source_t *ds;
+};
+typedef struct data_set_s data_set_t;
+
+enum notification_meta_type_e {
+ NM_TYPE_STRING,
+ NM_TYPE_SIGNED_INT,
+ NM_TYPE_UNSIGNED_INT,
+ NM_TYPE_DOUBLE,
+ NM_TYPE_BOOLEAN
+};
+
+typedef struct notification_meta_s {
+ char name[DATA_MAX_NAME_LEN];
+ enum notification_meta_type_e type;
+ union {
+ const char *nm_string;
+ int64_t nm_signed_int;
+ uint64_t nm_unsigned_int;
+ double nm_double;
+ bool nm_boolean;
+ } nm_value;
+ struct notification_meta_s *next;
+} notification_meta_t;
+
+typedef struct notification_s {
+ int severity;
+ cdtime_t time;
+ char message[NOTIF_MAX_MSG_LEN];
+ char host[DATA_MAX_NAME_LEN];
+ char plugin[DATA_MAX_NAME_LEN];
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ char type[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
+ notification_meta_t *meta;
+} notification_t;
+
+struct user_data_s {
+ void *data;
+ void (*free_func)(void *);
+};
+typedef struct user_data_s user_data_t;
+
+enum cache_event_type_e { CE_VALUE_NEW, CE_VALUE_UPDATE, CE_VALUE_EXPIRED };
+
+typedef struct cache_event_s {
+ enum cache_event_type_e type;
+ const value_list_t *value_list;
+ const char *value_list_name;
+ int ret;
+} cache_event_t;
+
+struct plugin_ctx_s {
+ char *name;
+ cdtime_t interval;
+ cdtime_t flush_interval;
+ cdtime_t flush_timeout;
+};
+typedef struct plugin_ctx_s plugin_ctx_t;
+
+/*
+ * Callback types
+ */
+typedef int (*plugin_init_cb)(void);
+typedef int (*plugin_read_cb)(user_data_t *);
+typedef int (*plugin_write_cb)(const data_set_t *, const value_list_t *,
+ user_data_t *);
+typedef int (*plugin_flush_cb)(cdtime_t timeout, const char *identifier,
+ user_data_t *);
+/* "missing" callback. Returns less than zero on failure, zero if other
+ * callbacks should be called, greater than zero if no more callbacks should be
+ * called. */
+typedef int (*plugin_missing_cb)(const value_list_t *, user_data_t *);
+/* "cache event" callback. CE_VALUE_NEW events are sent to all registered
+ * callbacks. Callback should check if it interested in further CE_VALUE_UPDATE
+ * and CE_VALUE_EXPIRED events for metric and set event->ret = 1 if so.
+ */
+typedef int (*plugin_cache_event_cb)(cache_event_t *, user_data_t *);
+typedef void (*plugin_log_cb)(int severity, const char *message, user_data_t *);
+typedef int (*plugin_shutdown_cb)(void);
+typedef int (*plugin_notification_cb)(const notification_t *, user_data_t *);
+/*
+ * NAME
+ * plugin_set_dir
+ *
+ * DESCRIPTION
+ * Sets the current `plugindir'
+ *
+ * ARGUMENTS
+ * `dir' Path to the plugin directory
+ *
+ * NOTES
+ * If `dir' is NULL the compiled in default `PLUGINDIR' is used.
+ */
+void plugin_set_dir(const char *dir);
+
+/*
+ * NAME
+ * plugin_load
+ *
+ * DESCRIPTION
+ * Searches the current `plugindir' (see `plugin_set_dir') for the plugin
+ * named $type and loads it. Afterwards the plugin's `module_register'
+ * function is called, which then calls `plugin_register' to register callback
+ * functions.
+ *
+ * ARGUMENTS
+ * `name' Name of the plugin to load.
+ * `global' Make this plugins symbols available for other shared libraries.
+ *
+ * RETURN VALUE
+ * Returns zero upon success, a value greater than zero if no plugin was found
+ * and a value below zero if an error occurs.
+ *
+ * NOTES
+ * Re-loading an already loaded module is detected and zero is returned in
+ * this case.
+ */
+int plugin_load(const char *name, bool global);
+bool plugin_is_loaded(char const *name);
+
+int plugin_init_all(void);
+void plugin_read_all(void);
+int plugin_read_all_once(void);
+int plugin_shutdown_all(void);
+
+/*
+ * NAME
+ * plugin_write
+ *
+ * DESCRIPTION
+ * Calls the write function of the given plugin with the provided data set and
+ * value list. It differs from `plugin_dispatch_values' in that it does not
+ * update the cache, does not do threshold checking, call the chain subsystem
+ * and so on. It looks up the requested plugin and invokes the function, end
+ * of story.
+ *
+ * ARGUMENTS
+ * plugin Name of the plugin. If NULL, the value is sent to all registered
+ * write functions.
+ * ds Pointer to the data_set_t structure. If NULL, the data set is
+ * looked up according to the `type' member in the `vl' argument.
+ * vl The actual value to be processed. Must not be NULL.
+ *
+ * RETURN VALUE
+ * Returns zero upon success or non-zero if an error occurred. If `plugin' is
+ * NULL and more than one plugin is called, an error is only returned if *all*
+ * plugins fail.
+ *
+ * NOTES
+ * This is the function used by the `write' built-in target. May be used by
+ * other target plugins.
+ */
+int plugin_write(const char *plugin, const data_set_t *ds,
+ const value_list_t *vl);
+
+int plugin_flush(const char *plugin, cdtime_t timeout, const char *identifier);
+
+/*
+ * The `plugin_register_*' functions are used to make `config', `init',
+ * `read', `write' and `shutdown' functions known to the plugin
+ * infrastructure. Also, the data-formats are made public like this.
+ */
+int plugin_register_config(const char *name,
+ int (*callback)(const char *key, const char *val),
+ const char **keys, int keys_num);
+int plugin_register_complex_config(const char *type,
+ int (*callback)(oconfig_item_t *));
+int plugin_register_init(const char *name, plugin_init_cb callback);
+int plugin_register_read(const char *name, int (*callback)(void));
+/* "user_data" will be freed automatically, unless
+ * "plugin_register_complex_read" returns an error (non-zero). */
+int plugin_register_complex_read(const char *group, const char *name,
+ plugin_read_cb callback, cdtime_t interval,
+ user_data_t const *user_data);
+int plugin_register_write(const char *name, plugin_write_cb callback,
+ user_data_t const *user_data);
+int plugin_register_flush(const char *name, plugin_flush_cb callback,
+ user_data_t const *user_data);
+int plugin_register_missing(const char *name, plugin_missing_cb callback,
+ user_data_t const *user_data);
+int plugin_register_cache_event(const char *name,
+ plugin_cache_event_cb callback,
+ user_data_t const *ud);
+int plugin_register_shutdown(const char *name, plugin_shutdown_cb callback);
+int plugin_register_data_set(const data_set_t *ds);
+int plugin_register_log(const char *name, plugin_log_cb callback,
+ user_data_t const *user_data);
+int plugin_register_notification(const char *name,
+ plugin_notification_cb callback,
+ user_data_t const *user_data);
+
+int plugin_unregister_config(const char *name);
+int plugin_unregister_complex_config(const char *name);
+int plugin_unregister_init(const char *name);
+int plugin_unregister_read(const char *name);
+int plugin_unregister_read_group(const char *group);
+int plugin_unregister_write(const char *name);
+int plugin_unregister_flush(const char *name);
+int plugin_unregister_missing(const char *name);
+int plugin_unregister_cache_event(const char *name);
+int plugin_unregister_shutdown(const char *name);
+int plugin_unregister_data_set(const char *name);
+int plugin_unregister_log(const char *name);
+int plugin_unregister_notification(const char *name);
+
+/*
+ * NAME
+ * plugin_log_available_writers
+ *
+ * DESCRIPTION
+ * This function can be called to output a list of _all_ registered
+ * writers to the logfacility.
+ * Since some writers dynamically build their name it can be hard for
+ * the configuring person to know it. This function will fill this gap.
+ */
+void plugin_log_available_writers(void);
+
+/*
+ * NAME
+ * plugin_dispatch_values
+ *
+ * DESCRIPTION
+ * This function is called by reading processes with the values they've
+ * aquired. The function fetches the data-set definition (that has been
+ * registered using `plugin_register_data_set') and calls _all_ registered
+ * write-functions.
+ *
+ * ARGUMENTS
+ * `vl' Value list of the values that have been read by a `read'
+ * function.
+ */
+int plugin_dispatch_values(value_list_t const *vl);
+
+/*
+ * NAME
+ * plugin_dispatch_multivalue
+ *
+ * SYNOPSIS
+ * plugin_dispatch_multivalue (vl, true, DS_TYPE_GAUGE,
+ * "free", 42.0,
+ * "used", 58.0,
+ * NULL);
+ *
+ * DESCRIPTION
+ * Takes a list of type instances and values and dispatches that in a batch,
+ * making sure that all values have the same time stamp. If "store_percentage"
+ * is set to true, the "type" is set to "percent" and a percentage is
+ * calculated and dispatched, rather than the absolute values. Values that are
+ * NaN are dispatched as NaN and will not influence the total.
+ *
+ * The variadic arguments is a list of type_instance / type pairs, that are
+ * interpreted as type "char const *" and type, encoded by their corresponding
+ * "store_type":
+ *
+ * - "gauge_t" when "DS_TYPE_GAUGE"
+ * - "absolute_t" when "DS_TYPE_ABSOLUTE"
+ * - "derive_t" when "DS_TYPE_DERIVE"
+ * - "counter_t" when "DS_TYPE_COUNTER"
+ *
+ * The last argument must be
+ * a NULL pointer to signal end-of-list.
+ *
+ * RETURNS
+ * The number of values it failed to dispatch (zero on success).
+ */
+__attribute__((sentinel)) int plugin_dispatch_multivalue(value_list_t const *vl,
+ bool store_percentage,
+ int store_type, ...);
+
+int plugin_dispatch_missing(const value_list_t *vl);
+void plugin_dispatch_cache_event(enum cache_event_type_e event_type,
+ unsigned long callbacks_mask, const char *name,
+ const value_list_t *vl);
+
+int plugin_dispatch_notification(const notification_t *notif);
+
+void plugin_log(int level, const char *format, ...)
+ __attribute__((format(printf, 2, 3)));
+
+/* These functions return the parsed severity or less than zero on failure. */
+int parse_log_severity(const char *severity);
+int parse_notif_severity(const char *severity);
+
+#define ERROR(...) plugin_log(LOG_ERR, __VA_ARGS__)
+#define WARNING(...) plugin_log(LOG_WARNING, __VA_ARGS__)
+#define NOTICE(...) plugin_log(LOG_NOTICE, __VA_ARGS__)
+#define INFO(...) plugin_log(LOG_INFO, __VA_ARGS__)
+#if COLLECT_DEBUG
+#define DEBUG(...) plugin_log(LOG_DEBUG, __VA_ARGS__)
+#else /* COLLECT_DEBUG */
+#define DEBUG(...) /* noop */
+#endif /* ! COLLECT_DEBUG */
+
+/* This will log messages, prefixed by plugin name */
+void daemon_log(int level, const char *format, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#define P_ERROR(...) daemon_log(LOG_ERR, __VA_ARGS__)
+#define P_WARNING(...) daemon_log(LOG_WARNING, __VA_ARGS__)
+#define P_NOTICE(...) daemon_log(LOG_NOTICE, __VA_ARGS__)
+#define P_INFO(...) daemon_log(LOG_INFO, __VA_ARGS__)
+
+const data_set_t *plugin_get_ds(const char *name);
+
+int plugin_notification_meta_add_string(notification_t *n, const char *name,
+ const char *value);
+int plugin_notification_meta_add_signed_int(notification_t *n, const char *name,
+ int64_t value);
+int plugin_notification_meta_add_unsigned_int(notification_t *n,
+ const char *name, uint64_t value);
+int plugin_notification_meta_add_double(notification_t *n, const char *name,
+ double value);
+int plugin_notification_meta_add_boolean(notification_t *n, const char *name,
+ bool value);
+
+int plugin_notification_meta_copy(notification_t *dst,
+ const notification_t *src);
+
+int plugin_notification_meta_free(notification_meta_t *n);
+
+/*
+ * Plugin context management.
+ */
+
+void plugin_init_ctx(void);
+
+plugin_ctx_t plugin_get_ctx(void);
+plugin_ctx_t plugin_set_ctx(plugin_ctx_t ctx);
+
+/*
+ * NAME
+ * plugin_get_interval
+ *
+ * DESCRIPTION
+ * This function returns the current value of the plugin's interval. The
+ * return value will be strictly greater than zero in all cases. If
+ * everything else fails, it will fall back to 10 seconds.
+ */
+cdtime_t plugin_get_interval(void);
+
+/*
+ * Context-aware thread management.
+ */
+
+int plugin_thread_create(pthread_t *thread, void *(*start_routine)(void *),
+ void *arg, char const *name);
+
+/*
+ * Plugins need to implement this
+ */
+
+void module_register(void);
+
+#endif /* PLUGIN_H */
diff --git a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
index 3703515dc..9db20be38 100644
--- a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
# Dependencies
find_package(Collectd REQUIRED)
@@ -36,7 +36,8 @@ list(APPEND INCLUDE_DIRS
${HICNPLUGIN_INCLUDE_DIRS}
${SAFE_VAPI_INCLUDE_DIRS}
${VPP_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR})
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ "${CMAKE_CURRENT_SOURCE_DIR}/../common")
list(APPEND LIBRARIES
${VPP_LIBRARY_VAPICLIENT}
diff --git a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
index 4228ac6e6..b6bc3af49 100644
--- a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
+++ b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
@@ -15,8 +15,7 @@
/* Keep order as it is */
#include <config.h>
-#include <collectd.h>
-#include <plugin.h>
+#include "common.h"
#define counter_t vpp_counter_t
#include <vapi/hicn.api.vapi.h>
@@ -26,15 +25,6 @@
DEFINE_VAPI_MSG_IDS_HICN_API_JSON
vapi_ctx_t vapi_ctx;
-#define STATIC_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
-
-#define IS_TRUE(s) \
- ((strcasecmp("true", (s)) == 0) || (strcasecmp("yes", (s)) == 0) || \
- (strcasecmp("on", (s)) == 0))
-#define IS_FALSE(s) \
- ((strcasecmp("false", (s)) == 0) || (strcasecmp("no", (s)) == 0) || \
- (strcasecmp("off", (s)) == 0))
-
/************** OPTIONS ***********************************/
static const char *config_keys[2] = {
"Verbose",
@@ -181,12 +171,6 @@ static data_set_t dtx_ds = {
/**********************************************************/
/********** UTILITY FUNCTIONS *****************************/
/**********************************************************/
-char *sstrncpy(char *dest, const char *src, size_t n) {
- strncpy(dest, src, n);
- dest[n - 1] = '\0';
- return dest;
-}
-
/*
* Utility function used by the read callback to populate a
* value_list_t and pass it to plugin_dispatch_values.
@@ -214,7 +198,6 @@ static int submit(const char *plugin_instance, const char *type,
/**********************************************************/
/********** CALLBACK FUNCTIONS ****************************/
/**********************************************************/
-
/*
* This function is called for each configuration item.
*/
diff --git a/telemetry/vpp-collectd/vpp/CMakeLists.txt b/telemetry/vpp-collectd/vpp/CMakeLists.txt
index 464ab42d8..c36787355 100644
--- a/telemetry/vpp-collectd/vpp/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp/CMakeLists.txt
@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-
# Dependencies
find_package(Vpp REQUIRED)
find_package(Collectd REQUIRED)
@@ -23,7 +21,8 @@ list(APPEND SOURCE_FILES
list(APPEND INCLUDE_DIRS
${COLLECTD_INCLUDE_DIRS}
${VPP_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR})
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ "${CMAKE_CURRENT_SOURCE_DIR}/../common")
list(APPEND LIBRARIES
${VPP_LIBRARY_VPPAPICLIENT}
diff --git a/telemetry/vpp-collectd/vpp/vpp.c b/telemetry/vpp-collectd/vpp/vpp.c
index 8bf5182a8..dcf956c93 100644
--- a/telemetry/vpp-collectd/vpp/vpp.c
+++ b/telemetry/vpp-collectd/vpp/vpp.c
@@ -15,23 +15,13 @@
/* Keep order as it is */
#include <config.h>
-#include <collectd.h>
-#include <plugin.h>
+#include "common.h"
#define counter_t vpp_counter_t
#include <vpp-api/client/stat_client.h>
#include <vppinfra/vec.h>
#undef counter_t
-#define STATIC_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
-
-#define IS_TRUE(s) \
- ((strcasecmp("true", (s)) == 0) || (strcasecmp("yes", (s)) == 0) || \
- (strcasecmp("on", (s)) == 0))
-#define IS_FALSE(s) \
- ((strcasecmp("false", (s)) == 0) || (strcasecmp("no", (s)) == 0) || \
- (strcasecmp("off", (s)) == 0))
-
/************** OPTIONS ***********************************/
static const char *config_keys[2] = {
"Verbose",
@@ -157,12 +147,6 @@ static data_set_t if_tx_broadcast_ds = {
/**********************************************************/
/********** UTILITY FUNCTIONS *****************************/
/**********************************************************/
-char *sstrncpy(char *dest, const char *src, size_t n) {
- strncpy(dest, src, n);
- dest[n - 1] = '\0';
- return dest;
-}
-
/*
* Utility function used by the read callback to populate a
* value_list_t and pass it to plugin_dispatch_values.
@@ -245,7 +229,6 @@ static int get_data_set(const char *stat_name, data_set_t *data_set_ptr) {
/**********************************************************/
/********** CALLBACK FUNCTIONS ****************************/
/**********************************************************/
-
/*
* This function is called for each configuration item.
*/
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
deleted file mode 100644
index 953b46339..000000000
--- a/utils/CMakeLists.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-set(CMAKE_CXX_STANDARD 14)
-
-project(utils)
-
-if (WIN32)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" )
-endif()
-
-set(CMAKE_MODULE_PATH
- ${CMAKE_MODULE_PATH}
- "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
-)
-
-if (NOT CMAKE_BUILD_TYPE)
- message(STATUS "${PROJECT_NAME}: No build type selected, default to Release")
- set(CMAKE_BUILD_TYPE "Release")
-endif ()
-
-include(BuildMacros)
-include(WindowsMacros)
-
-set(HICN_UTILS hicn-utils CACHE INTERNAL "" FORCE)
-
-if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package(Libtransport REQUIRED)
-else()
- if (DISABLE_SHARED_LIBRARIES)
- set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC})
- set(DEPENDENCIES ${LIBTRANSPORT_STATIC})
- else ()
- set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_SHARED})
- set(DEPENDENCIES ${LIBTRANSPORT_SHARED})
- endif ()
-
-endif()
-
-set(SUFFIX "")
-if (${LIBTRANSPORT_LIBRARIES} MATCHES ".*-memif.*")
- set(SUFFIX "-memif")
- set(LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs")
-endif()
-
-set(HICN_UTILS "${HICN_UTILS}${SUFFIX}")
-
-set (COMPILER_DEFINITIONS "")
-
-if (WIN32)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 /wd4996")
-endif ()
-
-include(Packaging)
-
-if (NOT DISABLE_EXECUTABLES)
- build_executable(hiperf
- SOURCES src/hiperf.cc
- LINK_LIBRARIES ${LIBTRANSPORT_LIBRARIES} ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${HICN_UTILS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- LINK_FLAGS ${LINK_FLAGS}
- )
-
- build_executable(hicn-ping-server
- SOURCES src/ping_server.cc
- LINK_LIBRARIES ${LIBTRANSPORT_LIBRARIES} ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${HICN_UTILS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- LINK_FLAGS ${LINK_FLAGS}
- )
-
- build_executable(hicn-ping-client
- SOURCES src/ping_client.cc
- LINK_LIBRARIES ${LIBTRANSPORT_LIBRARIES} ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
- DEPENDS ${DEPENDENCIES}
- COMPONENT ${HICN_UTILS}
- DEFINITIONS ${COMPILER_DEFINITIONS}
- LINK_FLAGS ${LINK_FLAGS}
- )
-endif ()
diff --git a/utils/cmake/Modules/Packaging.cmake b/utils/cmake/Modules/Packaging.cmake
deleted file mode 100644
index 783aa432a..000000000
--- a/utils/cmake/Modules/Packaging.cmake
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set(${HICN_UTILS}_DESCRIPTION
-"Hicn utils provide the hicn-ping and hiperf applications, \
-useful for testing and debugging within a hicn network."
- CACHE STRING "Description for deb/rpm package."
-)
-
-set(${HICN_UTILS}_DEB_DEPENDENCIES
- "lib${LIBTRANSPORT} (>= stable_version)"
- CACHE STRING "Dependencies for deb/rpm package."
-)
-
-set(${HICN_UTILS}_RPM_DEPENDENCIES
- "lib${LIBTRANSPORT} >= stable_version"
- CACHE STRING "Dependencies for deb/rpm package."
-) \ No newline at end of file
diff --git a/utils/src/hiperf.cc b/utils/src/hiperf.cc
deleted file mode 100644
index 9a1cf6236..000000000
--- a/utils/src/hiperf.cc
+++ /dev/null
@@ -1,1683 +0,0 @@
-/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hicn/transport/config.h>
-#include <hicn/transport/core/content_object.h>
-#include <hicn/transport/core/interest.h>
-#include <hicn/transport/interfaces/global_conf_interface.h>
-#include <hicn/transport/interfaces/p2psecure_socket_consumer.h>
-#include <hicn/transport/interfaces/p2psecure_socket_producer.h>
-#include <hicn/transport/interfaces/socket_consumer.h>
-#include <hicn/transport/interfaces/socket_producer.h>
-#include <hicn/transport/auth/identity.h>
-#include <hicn/transport/auth/signer.h>
-#include <hicn/transport/utils/chrono_typedefs.h>
-#include <hicn/transport/utils/literals.h>
-
-#ifndef _WIN32
-#include <hicn/transport/utils/daemonizator.h>
-#endif
-
-#include <asio.hpp>
-#include <cmath>
-#include <fstream>
-#include <iomanip>
-#include <sstream>
-#include <unordered_set>
-
-#ifdef __linux__
-#ifndef __ANDROID__
-#include <mcheck.h>
-#endif
-#endif
-
-#ifdef _WIN32
-#include <hicn/transport/portability/win_portability.h>
-#endif
-
-namespace transport {
-namespace interface {
-
-#ifndef ERROR_SUCCESS
-#define ERROR_SUCCESS 0
-#endif
-#define ERROR_SETUP -5
-#define MIN_PROBE_SEQ 0xefffffff
-
-struct packet_t {
- uint64_t timestamp;
- uint32_t size;
-};
-
-inline uint64_t _ntohll(const uint64_t *input) {
- uint64_t return_val;
- uint8_t *tmp = (uint8_t *)&return_val;
-
- tmp[0] = (uint8_t)(*input >> 56);
- tmp[1] = (uint8_t)(*input >> 48);
- tmp[2] = (uint8_t)(*input >> 40);
- tmp[3] = (uint8_t)(*input >> 32);
- tmp[4] = (uint8_t)(*input >> 24);
- tmp[5] = (uint8_t)(*input >> 16);
- tmp[6] = (uint8_t)(*input >> 8);
- tmp[7] = (uint8_t)(*input >> 0);
-
- return return_val;
-}
-
-inline uint64_t _htonll(const uint64_t *input) { return (_ntohll(input)); }
-
-struct nack_packet_t {
- uint64_t timestamp;
- uint32_t prod_rate;
- uint32_t prod_seg;
-
- inline uint64_t getTimestamp() const { return _ntohll(&timestamp); }
- inline void setTimestamp(uint64_t time) { timestamp = _htonll(&time); }
-
- inline uint32_t getProductionRate() const { return ntohl(prod_rate); }
- inline void setProductionRate(uint32_t rate) { prod_rate = htonl(rate); }
-
- inline uint32_t getProductionSegement() const { return ntohl(prod_seg); }
- inline void setProductionSegement(uint32_t seg) { prod_seg = htonl(seg); }
-};
-
-/**
- * Container for command line configuration for hiperf client.
- */
-struct ClientConfiguration {
- ClientConfiguration()
- : name("b001::abcd", 0),
- beta(-1.f),
- drop_factor(-1.f),
- window(-1),
- producer_certificate(""),
- passphrase(""),
- receive_buffer(nullptr),
- receive_buffer_size_(128 * 1024),
- download_size(0),
- report_interval_milliseconds_(1000),
- transport_protocol_(CBR),
- rtc_(false),
- test_mode_(false),
- secure_(false),
- producer_prefix_(),
- interest_lifetime_(500) {}
-
- Name name;
- double beta;
- double drop_factor;
- double window;
- std::string producer_certificate;
- std::string passphrase;
- std::shared_ptr<utils::MemBuf> receive_buffer;
- std::size_t receive_buffer_size_;
- std::size_t download_size;
- std::uint32_t report_interval_milliseconds_;
- TransportProtocolAlgorithms transport_protocol_;
- bool rtc_;
- bool test_mode_;
- bool secure_;
- Prefix producer_prefix_;
- uint32_t interest_lifetime_;
-};
-
-/**
- * Class for handling the production rate for the RTC producer.
- */
-class Rate {
- public:
- Rate() : rate_kbps_(0) {}
-
- Rate(const std::string &rate) {
- std::size_t found = rate.find("kbps");
- if (found != std::string::npos) {
- rate_kbps_ = std::stof(rate.substr(0, found));
- } else {
- throw std::runtime_error("Format " + rate + " not correct");
- }
- }
-
- Rate(const Rate &other) : rate_kbps_(other.rate_kbps_) {}
-
- Rate &operator=(const std::string &rate) {
- std::size_t found = rate.find("kbps");
- if (found != std::string::npos) {
- rate_kbps_ = std::stof(rate.substr(0, found));
- } else {
- throw std::runtime_error("Format " + rate + " not correct");
- }
-
- return *this;
- }
-
- std::chrono::microseconds getMicrosecondsForPacket(std::size_t packet_size) {
- return std::chrono::microseconds(
- (uint32_t)std::round(packet_size * 1000.0 * 8.0 / (double)rate_kbps_));
- }
-
- private:
- float rate_kbps_;
-};
-
-/**
- * Container for command line configuration for hiperf server.
- */
-struct ServerConfiguration {
- ServerConfiguration()
- : name("b001::abcd/64"),
- virtual_producer(true),
- manifest(false),
- live_production(false),
- sign(false),
- content_lifetime(600000000_U32),
- download_size(20 * 1024 * 1024),
- hash_algorithm(auth::CryptoHashType::SHA_256),
- keystore_name(""),
- passphrase(""),
- keystore_password("cisco"),
- multiphase_produce_(false),
- rtc_(false),
- interactive_(false),
- trace_based_(false),
- trace_index_(0),
- trace_file_(nullptr),
- production_rate_(std::string("2048kbps")),
- payload_size_(1400),
- secure_(false) {}
-
- Prefix name;
- bool virtual_producer;
- bool manifest;
- bool live_production;
- bool sign;
- std::uint32_t content_lifetime;
- std::uint32_t download_size;
- auth::CryptoHashType hash_algorithm;
- std::string keystore_name;
- std::string passphrase;
- std::string keystore_password;
- bool multiphase_produce_;
- bool rtc_;
- bool interactive_;
- bool trace_based_;
- std::uint32_t trace_index_;
- char *trace_file_;
- Rate production_rate_;
- std::size_t payload_size_;
- bool secure_;
- std::vector<struct packet_t> trace_;
-};
-
-/**
- * Forward declaration of client Read callbacks.
- */
-class RTCCallback;
-class Callback;
-class KeyCallback;
-
-/**
- * Hiperf client class: configure and setup an hicn consumer following the
- * ClientConfiguration.
- */
-class HIperfClient {
- typedef std::chrono::time_point<std::chrono::steady_clock> Time;
- typedef std::chrono::microseconds TimeDuration;
-
- friend class Callback;
- friend class KeyCallback;
- friend class RTCCallback;
-
- public:
- HIperfClient(const ClientConfiguration &conf)
- : configuration_(conf),
- total_duration_milliseconds_(0),
- old_bytes_value_(0),
- old_interest_tx_value_(0),
- old_fec_interest_tx_value_(0),
- old_fec_data_rx_value_(0),
- old_lost_data_value_(0),
- old_bytes_recovered_value_(0),
- old_retx_value_(0),
- old_sent_int_value_(0),
- old_received_nacks_value_(0),
- avg_data_delay_(0),
- delay_sample_(0),
- received_bytes_(0),
- received_data_pkt_(0),
- signals_(io_service_),
- expected_seg_(0),
- lost_packets_(std::unordered_set<uint32_t>()),
- rtc_callback_(*this),
- callback_(*this),
- key_callback_(*this) {}
-
- ~HIperfClient() {}
-
- void checkReceivedRtcContent(ConsumerSocket &c,
- const ContentObject &contentObject) {
- if (!configuration_.test_mode_) return;
-
- uint32_t receivedSeg = contentObject.getName().getSuffix();
- auto payload = contentObject.getPayload();
-
- if ((uint32_t)payload->length() == 16) { // 16 is the size of the NACK
- struct nack_packet_t *nack_pkt =
- (struct nack_packet_t *)contentObject.getPayload()->data();
- uint32_t productionSeg = nack_pkt->getProductionSegement();
- uint32_t productionRate = nack_pkt->getProductionRate();
-
- // uint32_t *payloadPtr = (uint32_t *)payload->data();
- // uint32_t productionSeg = *(payloadPtr);
- // uint32_t productionRate = *(++payloadPtr);
-
- if (productionRate == 0) {
- std::cout << "[STOP] producer is not producing content" << std::endl;
- return;
- }
-
- if (receivedSeg < productionSeg) {
- std::cout << "[OUT OF SYNCH] received NACK for " << receivedSeg
- << ". Next expected packet " << productionSeg + 1
- << std::endl;
- expected_seg_ = productionSeg;
- } else if (receivedSeg > productionSeg && receivedSeg < MIN_PROBE_SEQ) {
- std::cout << "[WINDOW TOO LARGE] received NACK for " << receivedSeg
- << ". Next expected packet " << productionSeg << std::endl;
- } else if (receivedSeg >= MIN_PROBE_SEQ) {
- std::cout << "[PROBE] probe number = " << receivedSeg << std::endl;
- }
- return;
- }
-
- received_bytes_ += (uint32_t)(payload->length() - 12);
- received_data_pkt_++;
-
- // collecting delay stats. Just for performance testing
- // XXX we should probably get the transport header (12) somewhere
- uint64_t *senderTimeStamp = (uint64_t *)(payload->data() + 12);
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
- double new_delay = (double)(now - *senderTimeStamp);
- if (*senderTimeStamp > now)
- new_delay = -1 * (double)(*senderTimeStamp - now);
-
- delay_sample_++;
- avg_data_delay_ =
- avg_data_delay_ + (new_delay - avg_data_delay_) / delay_sample_;
-
- if (receivedSeg > expected_seg_ && expected_seg_ != 0) {
- for (uint32_t i = expected_seg_; i < receivedSeg; i++) {
- std::cout << "[LOSS] lost packet " << i << std::endl;
- lost_packets_.insert(i);
- }
- expected_seg_ = receivedSeg + 1;
- return;
- } else if (receivedSeg < expected_seg_) {
- auto it = lost_packets_.find(receivedSeg);
- if (it != lost_packets_.end()) {
- std::cout << "[RECOVER] recovered packet " << receivedSeg << std::endl;
- lost_packets_.erase(it);
- } else {
- std::cout << "[OUT OF ORDER] recevied " << receivedSeg << " expedted "
- << expected_seg_ << std::endl;
- }
- return;
- }
- expected_seg_ = receivedSeg + 1;
- }
-
- void processLeavingInterest(ConsumerSocket &c, const Interest &interest) {}
-
- void handleTimerExpiration(ConsumerSocket &c,
- const TransportStatistics &stats) {
- const char separator = ' ';
- const int width = 15;
-
- utils::TimePoint t2 = utils::SteadyClock::now();
- auto exact_duration =
- std::chrono::duration_cast<utils::Milliseconds>(t2 - t_stats_);
-
- std::stringstream interval;
- interval << total_duration_milliseconds_ / 1000 << "-"
- << total_duration_milliseconds_ / 1000 +
- exact_duration.count() / 1000;
-
- std::stringstream bytes_transferred;
- bytes_transferred << std::fixed << std::setprecision(3)
- << (stats.getBytesRecv() - old_bytes_value_) / 1000000.0
- << std::setfill(separator) << "[MBytes]";
-
- std::stringstream bandwidth;
- bandwidth << ((stats.getBytesRecv() - old_bytes_value_) * 8) /
- (exact_duration.count()) / 1000.0
- << std::setfill(separator) << "[Mbps]";
-
- std::stringstream window;
- window << stats.getAverageWindowSize() << std::setfill(separator)
- << "[Int]";
-
- std::stringstream avg_rtt;
- avg_rtt << stats.getAverageRtt() << std::setfill(separator) << "[ms]";
-
- if (configuration_.rtc_) {
- // we get rtc stats more often, thus we need ms in the interval
- std::stringstream interval_ms;
- interval_ms << total_duration_milliseconds_ << "-"
- << total_duration_milliseconds_ + exact_duration.count();
-
- std::stringstream lost_data;
- lost_data << stats.getLostData() - old_lost_data_value_
- << std::setfill(separator) << "[pkt]";
-
- std::stringstream bytes_recovered_data;
- bytes_recovered_data << stats.getBytesRecoveredData() -
- old_bytes_recovered_value_
- << std::setfill(separator) << "[pkt]";
-
- std::stringstream data_delay;
- data_delay << avg_data_delay_ << std::setfill(separator) << "[ms]";
-
- std::stringstream received_data_pkt;
- received_data_pkt << received_data_pkt_ << std::setfill(separator)
- << "[pkt]";
-
- std::stringstream goodput;
- goodput << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0
- << std::setfill(separator) << "[Mbps]";
-
- std::stringstream loss_rate;
- loss_rate << std::fixed << std::setprecision(2)
- << stats.getLossRatio() * 100.0 << std::setfill(separator)
- << "[%]";
-
- std::stringstream retx_sent;
- retx_sent << stats.getRetxCount() - old_retx_value_
- << std::setfill(separator) << "[pkt]";
-
- std::stringstream interest_sent;
- interest_sent << stats.getInterestTx() - old_sent_int_value_
- << std::setfill(separator) << "[pkt]";
-
- std::stringstream nacks;
- nacks << stats.getReceivedNacks() - old_received_nacks_value_
- << std::setfill(separator) << "[pkt]";
-
- // statistics not yet available in the transport
- // std::stringstream interest_fec_tx;
- // interest_fec_tx << stats.getInterestFecTxCount() -
- // old_fec_interest_tx_value_ << std::setfill(separator) << "[pkt]";
- // std::stringstream bytes_fec_recv;
- // bytes_fec_recv << stats.getBytesFecRecv() - old_fec_data_rx_value_
- // << std::setfill(separator) << "[bytes]";
- std::cout << std::left << std::setw(width) << "Interval";
- std::cout << std::left << std::setw(width) << "RecvData";
- std::cout << std::left << std::setw(width) << "Bandwidth";
- std::cout << std::left << std::setw(width) << "Goodput";
- std::cout << std::left << std::setw(width) << "LossRate";
- std::cout << std::left << std::setw(width) << "Retr";
- std::cout << std::left << std::setw(width) << "InterestSent";
- std::cout << std::left << std::setw(width) << "ReceivedNacks";
- std::cout << std::left << std::setw(width) << "SyncWnd";
- std::cout << std::left << std::setw(width) << "MinRtt";
- std::cout << std::left << std::setw(width) << "LostData";
- std::cout << std::left << std::setw(width) << "RecoveredData";
- std::cout << std::left << std::setw(width) << "State";
- std::cout << std::left << std::setw(width) << "DataDelay" << std::endl;
-
- std::cout << std::left << std::setw(width) << interval_ms.str();
- std::cout << std::left << std::setw(width) << received_data_pkt.str();
- std::cout << std::left << std::setw(width) << bandwidth.str();
- std::cout << std::left << std::setw(width) << goodput.str();
- std::cout << std::left << std::setw(width) << loss_rate.str();
- std::cout << std::left << std::setw(width) << retx_sent.str();
- std::cout << std::left << std::setw(width) << interest_sent.str();
- std::cout << std::left << std::setw(width) << nacks.str();
- std::cout << std::left << std::setw(width) << window.str();
- std::cout << std::left << std::setw(width) << avg_rtt.str();
- std::cout << std::left << std::setw(width) << lost_data.str();
- std::cout << std::left << std::setw(width) << bytes_recovered_data.str();
- std::cout << std::left << std::setw(width) << stats.getCCStatus();
- std::cout << std::left << std::setw(width) << data_delay.str();
- std::cout << std::endl;
-
- // statistics not yet available in the transport
- // std::cout << std::left << std::setw(width) << interest_fec_tx.str();
- // std::cout << std::left << std::setw(width) << bytes_fec_recv.str();
- } else {
- std::cout << std::left << std::setw(width) << "Interval";
- std::cout << std::left << std::setw(width) << "Transfer";
- std::cout << std::left << std::setw(width) << "Bandwidth";
- std::cout << std::left << std::setw(width) << "Retr";
- std::cout << std::left << std::setw(width) << "Cwnd";
- std::cout << std::left << std::setw(width) << "AvgRtt" << std::endl;
-
- std::cout << std::left << std::setw(width) << interval.str();
- std::cout << std::left << std::setw(width) << bytes_transferred.str();
- std::cout << std::left << std::setw(width) << bandwidth.str();
- std::cout << std::left << std::setw(width) << stats.getRetxCount();
- std::cout << std::left << std::setw(width) << window.str();
- std::cout << std::left << std::setw(width) << avg_rtt.str() << std::endl;
- std::cout << std::endl;
- }
- total_duration_milliseconds_ += (uint32_t)exact_duration.count();
- old_bytes_value_ = stats.getBytesRecv();
- old_lost_data_value_ = stats.getLostData();
- old_bytes_recovered_value_ = stats.getBytesRecoveredData();
- old_fec_interest_tx_value_ = stats.getInterestFecTxCount();
- old_fec_data_rx_value_ = stats.getBytesFecRecv();
- old_retx_value_ = (uint32_t)stats.getRetxCount();
- old_sent_int_value_ = (uint32_t)stats.getInterestTx();
- old_received_nacks_value_ = stats.getReceivedNacks();
- delay_sample_ = 0;
- avg_data_delay_ = 0;
- received_bytes_ = 0;
- received_data_pkt_ = 0;
-
- t_stats_ = utils::SteadyClock::now();
- }
-
- int setup() {
- int ret;
-
- if (configuration_.rtc_) {
- configuration_.transport_protocol_ = RTC;
- } else if (configuration_.window < 0) {
- configuration_.transport_protocol_ = RAAQM;
- } else {
- configuration_.transport_protocol_ = CBR;
- }
-
- if (configuration_.secure_) {
- consumer_socket_ = std::make_shared<P2PSecureConsumerSocket>(
- RAAQM, configuration_.transport_protocol_);
- if (configuration_.producer_prefix_.getPrefixLength() == 0) {
- std::cerr << "ERROR -- Missing producer prefix on which perform the "
- "handshake."
- << std::endl;
- } else {
- P2PSecureConsumerSocket &secure_consumer_socket =
- *(static_cast<P2PSecureConsumerSocket *>(consumer_socket_.get()));
- secure_consumer_socket.registerPrefix(configuration_.producer_prefix_);
- }
- } else {
- consumer_socket_ =
- std::make_shared<ConsumerSocket>(configuration_.transport_protocol_);
- }
-
- consumer_socket_->setSocketOption(
- GeneralTransportOptions::INTEREST_LIFETIME,
- configuration_.interest_lifetime_);
-
-#if defined(DEBUG) && defined(__linux__)
- std::shared_ptr<transport::BasePortal> portal;
- consumer_socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal);
- signals_ =
- std::make_unique<asio::signal_set>(portal->getIoService(), SIGUSR1);
- signals_->async_wait([this](const std::error_code &, const int &) {
- std::cout << "Signal SIGUSR1!" << std::endl;
- mtrace();
- });
-#endif
-
- if (consumer_socket_->setSocketOption(CURRENT_WINDOW_SIZE,
- configuration_.window) ==
- SOCKET_OPTION_NOT_SET) {
- std::cerr << "ERROR -- Impossible to set the size of the window."
- << std::endl;
- return ERROR_SETUP;
- }
-
- if (configuration_.transport_protocol_ == RAAQM &&
- configuration_.beta != -1.f) {
- if (consumer_socket_->setSocketOption(RaaqmTransportOptions::BETA_VALUE,
- configuration_.beta) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- }
-
- if (configuration_.transport_protocol_ == RAAQM &&
- configuration_.drop_factor != -1.f) {
- if (consumer_socket_->setSocketOption(RaaqmTransportOptions::DROP_FACTOR,
- configuration_.drop_factor) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- }
-
- if (!configuration_.producer_certificate.empty()) {
- std::shared_ptr<auth::Verifier> verifier =
- std::make_shared<auth::AsymmetricVerifier>(
- configuration_.producer_certificate);
- if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
- verifier) == SOCKET_OPTION_NOT_SET)
- return ERROR_SETUP;
- }
-
- if (!configuration_.passphrase.empty()) {
- std::shared_ptr<auth::Verifier> verifier =
- std::make_shared<auth::SymmetricVerifier>(configuration_.passphrase);
- if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
- verifier) == SOCKET_OPTION_NOT_SET)
- return ERROR_SETUP;
- }
-
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::INTEREST_OUTPUT,
- (ConsumerInterestCallback)std::bind(
- &HIperfClient::processLeavingInterest, this, std::placeholders::_1,
- std::placeholders::_2));
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (!configuration_.rtc_) {
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, &callback_);
- } else {
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, &rtc_callback_);
- }
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (configuration_.rtc_) {
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
- (ConsumerContentObjectCallback)std::bind(
- &HIperfClient::checkReceivedRtcContent, this,
- std::placeholders::_1, std::placeholders::_2));
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- }
-
- if (configuration_.rtc_) {
- std::shared_ptr<TransportStatistics> transport_stats;
- consumer_socket_->getSocketOption(
- OtherOptions::STATISTICS, (TransportStatistics **)&transport_stats);
- transport_stats->setAlpha(0.0);
- }
-
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::STATS_SUMMARY,
- (ConsumerTimerCallback)std::bind(&HIperfClient::handleTimerExpiration,
- this, std::placeholders::_1,
- std::placeholders::_2));
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (consumer_socket_->setSocketOption(
- GeneralTransportOptions::STATS_INTERVAL,
- configuration_.report_interval_milliseconds_) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- consumer_socket_->connect();
-
- return ERROR_SUCCESS;
- }
-
- int run() {
- std::cout << "Starting download of " << configuration_.name << std::endl;
-
- signals_.add(SIGINT);
- signals_.async_wait(
- [this](const std::error_code &, const int &) { io_service_.stop(); });
-
- t_download_ = t_stats_ = std::chrono::steady_clock::now();
- consumer_socket_->asyncConsume(configuration_.name);
- io_service_.run();
-
- consumer_socket_->stop();
-
- return ERROR_SUCCESS;
- }
-
- private:
- class RTCCallback : public ConsumerSocket::ReadCallback {
- static constexpr std::size_t mtu = 1500;
-
- public:
- RTCCallback(HIperfClient &hiperf_client) : client_(hiperf_client) {
- client_.configuration_.receive_buffer = utils::MemBuf::create(mtu);
- }
-
- bool isBufferMovable() noexcept override { return false; }
-
- void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override {
- *application_buffer =
- client_.configuration_.receive_buffer->writableData();
- *max_length = mtu;
- }
-
- void readDataAvailable(std::size_t length) noexcept override {}
-
- size_t maxBufferSize() const override { return mtu; }
-
- void readError(const std::error_code ec) noexcept override {
- std::cerr << "Error while reading from RTC socket" << std::endl;
- client_.io_service_.stop();
- }
-
- void readSuccess(std::size_t total_size) noexcept override {
- std::cout << "Data successfully read" << std::endl;
- }
-
- private:
- HIperfClient &client_;
- };
-
- class Callback : public ConsumerSocket::ReadCallback {
- public:
- Callback(HIperfClient &hiperf_client) : client_(hiperf_client) {
- client_.configuration_.receive_buffer =
- utils::MemBuf::create(client_.configuration_.receive_buffer_size_);
- }
-
- bool isBufferMovable() noexcept override { return false; }
-
- void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override {
- *application_buffer =
- client_.configuration_.receive_buffer->writableData();
- *max_length = client_.configuration_.receive_buffer_size_;
- }
-
- void readDataAvailable(std::size_t length) noexcept override {}
-
- void readBufferAvailable(
- std::unique_ptr<utils::MemBuf> &&buffer) noexcept override {}
-
- size_t maxBufferSize() const override {
- return client_.configuration_.receive_buffer_size_;
- }
-
- void readError(const std::error_code ec) noexcept override {
- std::cerr << "Error " << ec.message() << " while reading from socket"
- << std::endl;
- client_.io_service_.stop();
- }
-
- void readSuccess(std::size_t total_size) noexcept override {
- Time t2 = std::chrono::steady_clock::now();
- TimeDuration dt =
- std::chrono::duration_cast<TimeDuration>(t2 - client_.t_download_);
- long usec = (long)dt.count();
-
- std::cout << "Content retrieved. Size: " << total_size << " [Bytes]"
- << std::endl;
-
- std::cerr << "Elapsed Time: " << usec / 1000000.0 << " seconds -- "
- << (total_size * 8) * 1.0 / usec * 1.0 << " [Mbps]"
- << std::endl;
-
- client_.io_service_.stop();
- }
-
- private:
- HIperfClient &client_;
- };
-
- class KeyCallback : public ConsumerSocket::ReadCallback {
- static constexpr std::size_t read_size = 16 * 1024;
-
- public:
- KeyCallback(HIperfClient &hiperf_client)
- : client_(hiperf_client), key_(nullptr) {}
-
- bool isBufferMovable() noexcept override { return true; }
-
- void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override {}
-
- void readDataAvailable(std::size_t length) noexcept override {}
-
- void readBufferAvailable(
- std::unique_ptr<utils::MemBuf> &&buffer) noexcept override {
- key_ = std::make_unique<std::string>((const char *)buffer->data(),
- buffer->length());
- std::cout << "Key: " << *key_ << std::endl;
- }
-
- size_t maxBufferSize() const override { return read_size; }
-
- void readError(const std::error_code ec) noexcept override {
- std::cerr << "Error " << ec.message() << " while reading from socket"
- << std::endl;
- client_.io_service_.stop();
- }
-
- bool validateKey() { return !key_->empty(); }
-
- void readSuccess(std::size_t total_size) noexcept override {
- std::cout << "Key size: " << total_size << " bytes" << std::endl;
- }
-
- void setConsumer(std::shared_ptr<ConsumerSocket> consumer_socket) {
- consumer_socket_ = consumer_socket;
- }
-
- private:
- HIperfClient &client_;
- std::unique_ptr<std::string> key_;
- std::shared_ptr<ConsumerSocket> consumer_socket_;
- };
-
- ClientConfiguration configuration_;
- Time t_stats_;
- Time t_download_;
- uint32_t total_duration_milliseconds_;
- uint64_t old_bytes_value_;
- uint64_t old_interest_tx_value_;
- uint64_t old_fec_interest_tx_value_;
- uint64_t old_fec_data_rx_value_;
- uint64_t old_lost_data_value_;
- uint64_t old_bytes_recovered_value_;
- uint32_t old_retx_value_;
- uint32_t old_sent_int_value_;
- uint32_t old_received_nacks_value_;
-
- // IMPORTANT: to be used only for performance testing, when consumer and
- // producer are synchronized. Used for rtc only at the moment
- double avg_data_delay_;
- uint32_t delay_sample_;
-
- uint32_t received_bytes_;
- uint32_t received_data_pkt_;
-
- asio::io_service io_service_;
- asio::signal_set signals_;
- uint32_t expected_seg_;
- std::unordered_set<uint32_t> lost_packets_;
- RTCCallback rtc_callback_;
- Callback callback_;
- KeyCallback key_callback_;
- std::shared_ptr<ConsumerSocket> consumer_socket_;
-}; // namespace interface
-
-/**
- * Hiperf server class: configure and setup an hicn producer following the
- * ServerConfiguration.
- */
-class HIperfServer {
- const std::size_t log2_content_object_buffer_size = 8;
-
- public:
- HIperfServer(ServerConfiguration &conf)
- : configuration_(conf),
- signals_(io_service_),
- rtc_timer_(io_service_),
- unsatisfied_interests_(),
- content_objects_((std::uint16_t)(1 << log2_content_object_buffer_size)),
- content_objects_index_(0),
- mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1),
- last_segment_(0),
-#ifndef _WIN32
- ptr_last_segment_(&last_segment_),
- input_(io_service_),
- rtc_running_(false),
-#else
- ptr_last_segment_(&last_segment_),
-#endif
- flow_name_(configuration_.name.getName()) {
- std::string buffer(configuration_.payload_size_, 'X');
- std::cout << "Producing contents under name " << conf.name.getName()
- << std::endl;
-#ifndef _WIN32
- if (configuration_.interactive_) {
- input_.assign(::dup(STDIN_FILENO));
- }
-#endif
-
- for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) {
- content_objects_[i] = ContentObject::Ptr(
- new ContentObject(conf.name.getName(), HF_INET6_TCP, 0,
- (const uint8_t *)buffer.data(), buffer.size()));
- content_objects_[i]->setLifetime(
- default_values::content_object_expiry_time);
- }
- }
-
- void virtualProcessInterest(ProducerSocket &p, const Interest &interest) {
- // std::cout << "Received interest " << interest.getName() << std::endl;
- content_objects_[content_objects_index_ & mask_]->setName(
- interest.getName());
- producer_socket_->produce(
- *content_objects_[content_objects_index_++ & mask_]);
- }
-
- void processInterest(ProducerSocket &p, const Interest &interest) {
- p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)VOID_HANDLER);
- p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
- 5000000_U32);
-
- produceContent(p, interest.getName(), interest.getName().getSuffix());
- std::cout << "Received interest " << interest.getName().getSuffix()
- << std::endl;
- }
-
- void asyncProcessInterest(ProducerSocket &p, const Interest &interest) {
- p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(
- &HIperfServer::cacheMiss, this, std::placeholders::_1,
- std::placeholders::_2));
- p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
- 5000000_U32);
- uint32_t suffix = interest.getName().getSuffix();
-
- if (suffix == 0) {
- last_segment_ = 0;
- ptr_last_segment_ = &last_segment_;
- unsatisfied_interests_.clear();
- }
-
- // The suffix will either be the one from the received interest or the
- // smallest suffix of a previous interest not satisfed
- if (!unsatisfied_interests_.empty()) {
- auto it =
- std::lower_bound(unsatisfied_interests_.begin(),
- unsatisfied_interests_.end(), *ptr_last_segment_);
- if (it != unsatisfied_interests_.end()) {
- suffix = *it;
- }
- unsatisfied_interests_.erase(unsatisfied_interests_.begin(), it);
- }
-
- std::cout << "Received interest " << interest.getName().getSuffix()
- << ", starting production at " << suffix << std::endl;
- std::cout << unsatisfied_interests_.size() << " interests still unsatisfied"
- << std::endl;
- produceContentAsync(p, interest.getName(), suffix);
- }
-
- void produceContent(ProducerSocket &p, const Name &content_name,
- uint32_t suffix) {
- auto b = utils::MemBuf::create(configuration_.download_size);
- std::memset(b->writableData(), '?', configuration_.download_size);
- b->append(configuration_.download_size);
- uint32_t total;
-
- utils::TimePoint t0 = utils::SteadyClock::now();
- total = p.produceStream(content_name, std::move(b),
- !configuration_.multiphase_produce_, suffix);
- utils::TimePoint t1 = utils::SteadyClock::now();
-
- std::cout
- << "Written " << total
- << " data packets in output buffer (Segmentation time: "
- << std::chrono::duration_cast<utils::Microseconds>(t1 - t0).count()
- << " us)" << std::endl;
- }
-
- void produceContentAsync(ProducerSocket &p, Name content_name,
- uint32_t suffix) {
- auto b = utils::MemBuf::create(configuration_.download_size);
- std::memset(b->writableData(), '?', configuration_.download_size);
- b->append(configuration_.download_size);
-
- p.asyncProduce(content_name, std::move(b),
- !configuration_.multiphase_produce_, suffix,
- &ptr_last_segment_);
- }
-
- void cacheMiss(ProducerSocket &p, const Interest &interest) {
- unsatisfied_interests_.push_back(interest.getName().getSuffix());
- }
-
- void onContentProduced(ProducerSocket &p, const std::error_code &err,
- uint64_t bytes_written) {
- p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(
- &HIperfServer::asyncProcessInterest, this,
- std::placeholders::_1, std::placeholders::_2));
- }
-
- std::shared_ptr<auth::Identity> getProducerIdentity(
- std::string &keystore_path, std::string &keystore_pwd,
- auth::CryptoHashType &hash_type) {
- if (access(keystore_path.c_str(), F_OK) != -1) {
- return std::make_shared<auth::Identity>(keystore_path, keystore_pwd,
- hash_type);
- }
- return std::make_shared<auth::Identity>(keystore_path, keystore_pwd,
- auth::CryptoSuite::RSA_SHA256, 1024,
- 365, "producer-test");
- }
-
- int setup() {
- int ret;
- int production_protocol;
-
- if (configuration_.secure_) {
- auto identity = getProducerIdentity(configuration_.keystore_name,
- configuration_.keystore_password,
- configuration_.hash_algorithm);
- producer_socket_ = std::make_unique<P2PSecureProducerSocket>(
- configuration_.rtc_, identity);
- } else {
- if (!configuration_.rtc_) {
- production_protocol = ProductionProtocolAlgorithms::BYTE_STREAM;
- } else {
- production_protocol = ProductionProtocolAlgorithms::RTC_PROD;
- }
-
- producer_socket_ = std::make_unique<ProducerSocket>(production_protocol);
- }
-
- if (configuration_.sign) {
- std::shared_ptr<auth::Signer> signer;
-
- if (!configuration_.passphrase.empty()) {
- signer = std::make_shared<auth::SymmetricSigner>(
- auth::CryptoSuite::HMAC_SHA256, configuration_.passphrase);
- } else if (!configuration_.keystore_name.empty()) {
- auto identity = getProducerIdentity(configuration_.keystore_name,
- configuration_.keystore_password,
- configuration_.hash_algorithm);
- signer = identity->getSigner();
- } else {
- return ERROR_SETUP;
- }
-
- if (producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER,
- signer) == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- }
-
- uint32_t rtc_header_size = 0;
- if (configuration_.rtc_) rtc_header_size = 12;
- producer_socket_->setSocketOption(
- GeneralTransportOptions::DATA_PACKET_SIZE,
- (uint32_t)(
- configuration_.payload_size_ + rtc_header_size +
- (configuration_.name.getAddressFamily() == AF_INET ? 40 : 60)));
- producer_socket_->registerPrefix(configuration_.name);
- producer_socket_->connect();
-
- if (configuration_.rtc_) {
- std::cout << "Running RTC producer: the prefix length will be ignored."
- " Use /128 by default in RTC mode"
- << std::endl;
- return ERROR_SUCCESS;
- }
-
- if (!configuration_.virtual_producer) {
- if (producer_socket_->setSocketOption(
- GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
- configuration_.content_lifetime) == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (producer_socket_->setSocketOption(
- GeneralTransportOptions::MAKE_MANIFEST,
- configuration_.manifest) == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (producer_socket_->setSocketOption(
- GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 200000U) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (!configuration_.live_production) {
- produceContent(*producer_socket_, configuration_.name.getName(), 0);
- } else {
- ret = producer_socket_->setSocketOption(
- ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(&HIperfServer::asyncProcessInterest,
- this, std::placeholders::_1,
- std::placeholders::_2));
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- }
- } else {
- ret = producer_socket_->setSocketOption(
- GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U);
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- ret = producer_socket_->setSocketOption(
- ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(&HIperfServer::virtualProcessInterest,
- this, std::placeholders::_1,
- std::placeholders::_2));
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- }
-
- ret = producer_socket_->setSocketOption(
- ProducerCallbacksOptions::CONTENT_PRODUCED,
- (ProducerContentCallback)bind(
- &HIperfServer::onContentProduced, this, std::placeholders::_1,
- std::placeholders::_2, std::placeholders::_3));
-
- return ERROR_SUCCESS;
- }
-
- void sendRTCContentObjectCallback(std::error_code ec) {
- if (ec) return;
- rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
- rtc_timer_.async_wait(std::bind(&HIperfServer::sendRTCContentObjectCallback,
- this, std::placeholders::_1));
- auto payload =
- content_objects_[content_objects_index_++ & mask_]->getPayload();
-
- // this is used to compute the data packet delay
- // Used only for performance evaluation
- // It requires clock synchronization between producer and consumer
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
-
- std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
-
- producer_socket_->produceDatagram(
- flow_name_, payload->data(),
- payload->length() < 1400 ? payload->length() : 1400);
- }
-
- void sendRTCContentObjectCallbackWithTrace(std::error_code ec) {
- if (ec) return;
-
- auto payload =
- content_objects_[content_objects_index_++ & mask_]->getPayload();
-
- uint32_t packet_len =
- configuration_.trace_[configuration_.trace_index_].size;
-
- // this is used to compute the data packet delay
- // used only for performance evaluation
- // it requires clock synchronization between producer and consumer
- uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now().time_since_epoch())
- .count();
-
- std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
-
- if (packet_len > payload->length()) packet_len = (uint32_t)payload->length();
- if (packet_len > 1400) packet_len = 1400;
-
- producer_socket_->produceDatagram(flow_name_, payload->data(), packet_len);
-
- uint32_t next_index = configuration_.trace_index_ + 1;
- uint64_t schedule_next;
- if (next_index < configuration_.trace_.size()) {
- schedule_next =
- configuration_.trace_[next_index].timestamp -
- configuration_.trace_[configuration_.trace_index_].timestamp;
- } else {
- // here we need to loop, schedule in a random time
- schedule_next = 1000;
- }
-
- configuration_.trace_index_ =
- (configuration_.trace_index_ + 1) % configuration_.trace_.size();
- rtc_timer_.expires_from_now(std::chrono::microseconds(schedule_next));
- rtc_timer_.async_wait(
- std::bind(&HIperfServer::sendRTCContentObjectCallbackWithTrace, this,
- std::placeholders::_1));
- }
-
-#ifndef _WIN32
- void handleInput(const std::error_code &error, std::size_t length) {
- if (error) {
- producer_socket_->stop();
- io_service_.stop();
- }
-
- if (rtc_running_) {
- std::cout << "stop real time content production" << std::endl;
- rtc_running_ = false;
- rtc_timer_.cancel();
- } else {
- std::cout << "start real time content production" << std::endl;
- rtc_running_ = true;
- rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
- rtc_timer_.async_wait(
- std::bind(&HIperfServer::sendRTCContentObjectCallback, this,
- std::placeholders::_1));
- }
-
- input_buffer_.consume(length); // Remove newline from input.
- asio::async_read_until(
- input_, input_buffer_, '\n',
- std::bind(&HIperfServer::handleInput, this, std::placeholders::_1,
- std::placeholders::_2));
- }
-#endif
-
- int parseTraceFile() {
- std::ifstream trace(configuration_.trace_file_);
- if (trace.fail()) {
- return -1;
- }
- std::string line;
- while (std::getline(trace, line)) {
- std::istringstream iss(line);
- struct packet_t packet;
- iss >> packet.timestamp >> packet.size;
- configuration_.trace_.push_back(packet);
- }
- return 0;
- }
-
- int run() {
- std::cerr << "Starting to serve consumers" << std::endl;
-
- signals_.add(SIGINT);
- signals_.async_wait([this](const std::error_code &, const int &) {
- std::cout << "STOPPING!!" << std::endl;
- producer_socket_->stop();
- io_service_.stop();
- });
-
- if (configuration_.rtc_) {
-#ifndef _WIN32
- if (configuration_.interactive_) {
- asio::async_read_until(
- input_, input_buffer_, '\n',
- std::bind(&HIperfServer::handleInput, this, std::placeholders::_1,
- std::placeholders::_2));
- } else if (configuration_.trace_based_) {
- std::cout << "trace-based mode enabled" << std::endl;
- if (configuration_.trace_file_ == nullptr) {
- std::cout << "cannot find the trace file" << std::endl;
- return ERROR_SETUP;
- }
- if (parseTraceFile() < 0) {
- std::cout << "cannot parse the trace file" << std::endl;
- return ERROR_SETUP;
- }
- rtc_running_ = true;
- rtc_timer_.expires_from_now(std::chrono::milliseconds(1));
- rtc_timer_.async_wait(
- std::bind(&HIperfServer::sendRTCContentObjectCallbackWithTrace,
- this, std::placeholders::_1));
- } else {
- rtc_running_ = true;
- rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
- rtc_timer_.async_wait(
- std::bind(&HIperfServer::sendRTCContentObjectCallback, this,
- std::placeholders::_1));
- }
-#else
- rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
- rtc_timer_.async_wait(
- std::bind(&HIperfServer::sendRTCContentObjectCallback, this,
- std::placeholders::_1));
-#endif
- }
-
- io_service_.run();
-
- return ERROR_SUCCESS;
- }
-
- private:
- ServerConfiguration configuration_;
- asio::io_service io_service_;
- asio::signal_set signals_;
- asio::steady_timer rtc_timer_;
- std::vector<uint32_t> unsatisfied_interests_;
- std::vector<std::shared_ptr<ContentObject>> content_objects_;
- std::uint16_t content_objects_index_;
- std::uint16_t mask_;
- std::uint32_t last_segment_;
- std::uint32_t *ptr_last_segment_;
- std::unique_ptr<ProducerSocket> producer_socket_;
-#ifndef _WIN32
- asio::posix::stream_descriptor input_;
- asio::streambuf input_buffer_;
- bool rtc_running_;
-
-#endif
- core::Name flow_name_;
-}; // namespace interface
-
-void usage() {
- std::cerr << "HIPERF - A tool for performing network throughput "
- "measurements with hICN"
- << std::endl;
- std::cerr << "usage: hiperf [-S|-C] [options] [prefix|name]" << std::endl;
- std::cerr << std::endl;
- std::cerr << "SERVER OR CLIENT:" << std::endl;
-#ifndef _WIN32
- std::cerr << "-D\t\t\t\t\t"
- << "Run as a daemon" << std::endl;
- std::cerr << "-R\t\t\t\t\t"
- << "Run RTC protocol (client or server)" << std::endl;
- std::cerr << "-f\t<filename>\t\t\t"
- << "Log file" << std::endl;
- std::cerr << "-z\t<io_module>\t\t\t"
- << "IO module to use. Default: hicnlight_module" << std::endl;
-#endif
- std::cerr << std::endl;
- std::cerr << "SERVER SPECIFIC:" << std::endl;
- std::cerr << "-A\t<content_size>\t\t\t"
- "Size of the content to publish. This "
- "is not the size of the packet (see -s for it)."
- << std::endl;
- std::cerr << "-s\t<packet_size>\t\t\tSize of the payload of each data packet."
- << std::endl;
- std::cerr << "-r\t\t\t\t\t"
- << "Produce real content of <content_size> bytes" << std::endl;
- std::cerr << "-m\t\t\t\t\t"
- << "Produce transport manifest" << std::endl;
- std::cerr << "-l\t\t\t\t\t"
- << "Start producing content upon the reception of the "
- "first interest"
- << std::endl;
- std::cerr << "-K\t<keystore_path>\t\t\t"
- << "Path of p12 file containing the "
- "crypto material used for signing packets"
- << std::endl;
- std::cerr << "-k\t<passphrase>\t\t\t"
- << "String from which a 128-bit symmetric key will be "
- "derived for signing packets"
- << std::endl;
- std::cerr << "-y\t<hash_algorithm>\t\t"
- << "Use the selected hash algorithm for "
- "calculating manifest digests"
- << std::endl;
- std::cerr << "-p\t<password>\t\t\t"
- << "Password for p12 keystore" << std::endl;
- std::cerr << "-x\t\t\t\t\t"
- << "Produce a content of <content_size>, then after downloading "
- "it produce a new content of"
- << "\n\t\t\t\t\t<content_size> without resetting "
- "the suffix to 0."
- << std::endl;
- std::cerr << "-B\t<bitrate>\t\t\t"
- << "Bitrate for RTC producer, to be used with the -R option."
- << std::endl;
-#ifndef _WIN32
- std::cerr << "-I\t\t\t\t\t"
- "Interactive mode, start/stop real time content production "
- "by pressing return. To be used with the -R option"
- << std::endl;
- std::cerr
- << "-T\t<filename>\t\t\t"
- "Trace based mode, hiperf takes as input a file with a trace. "
- "Each line of the file indicates the timestamp and the size of "
- "the packet to generate. To be used with the -R option. -B and -I "
- "will be ignored."
- << std::endl;
- std::cerr << "-E\t\t\t\t\t"
- << "Enable encrypted communication. Requires the path to a p12 "
- "file containing the "
- "crypto material used for the TLS handshake"
- << std::endl;
-#endif
- std::cerr << std::endl;
- std::cerr << "CLIENT SPECIFIC:" << std::endl;
- std::cerr << "-b\t<beta_parameter>\t\t"
- << "RAAQM beta parameter" << std::endl;
- std::cerr << "-d\t<drop_factor_parameter>\t\t"
- << "RAAQM drop factor "
- "parameter"
- << std::endl;
- std::cerr << "-L\t<interest lifetime>\t\t"
- << "Set interest lifetime." << std::endl;
- std::cerr << "-M\t<input_buffer_size>\t\t"
- << "Size of consumer input buffer. If 0, reassembly of packets "
- "will be disabled."
- << std::endl;
- std::cerr << "-W\t<window_size>\t\t\t"
- << "Use a fixed congestion window "
- "for retrieving the data."
- << std::endl;
- std::cerr << "-i\t<stats_interval>\t\t"
- << "Show the statistics every <stats_interval> milliseconds."
- << std::endl;
- std::cerr << "-c\t<certificate_path>\t\t"
- << "Path of the producer certificate to be used for verifying the "
- "origin of the packets received."
- << std::endl;
- std::cerr << "-k\t<passphrase>\t\t\t"
- << "String from which is derived the symmetric key used by the "
- "producer to sign packets and by the consumer to verify them."
- << std::endl;
- std::cerr << "-t\t\t\t\t\t"
- "Test mode, check if the client is receiving the "
- "correct data. This is an RTC specific option, to be "
- "used with the -R (default false)"
- << std::endl;
- std::cerr << "-P\t\t\t\t\t"
- << "Prefix of the producer where to do the handshake" << std::endl;
-}
-
-int main(int argc, char *argv[]) {
-#ifndef _WIN32
- // Common
- bool daemon = false;
-#else
- WSADATA wsaData = {0};
- WSAStartup(MAKEWORD(2, 2), &wsaData);
-#endif
-
- // -1 server, 0 undefined, 1 client
- int role = 0;
- int options = 0;
-
- char *log_file = nullptr;
- interface::global_config::IoModuleConfiguration config;
- std::string conf_file;
- config.name = "hicnlight_module";
-
- // Consumer
- ClientConfiguration client_configuration;
-
- // Producer
- ServerConfiguration server_configuration;
-
- int opt;
-#ifndef _WIN32
- while ((opt = getopt(
- argc, argv,
- "DSCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xE:P:B:ItL:z:T:F:")) != -1) {
- switch (opt) {
- // Common
- case 'D': {
- daemon = true;
- break;
- }
- case 'I': {
- server_configuration.interactive_ = true;
- server_configuration.trace_based_ = false;
- break;
- }
- case 'T': {
- server_configuration.interactive_ = false;
- server_configuration.trace_based_ = true;
- server_configuration.trace_file_ = optarg;
- break;
- }
-#else
- while ((opt = getopt(argc, argv,
- "SCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xB:E:P:tL:z:F:")) !=
- -1) {
- switch (opt) {
-#endif
- case 'f': {
- log_file = optarg;
- break;
- }
- case 'R': {
- client_configuration.rtc_ = true;
- server_configuration.rtc_ = true;
- break;
- }
- case 'z': {
- config.name = optarg;
- break;
- }
- case 'F': {
- conf_file = optarg;
- break;
- }
-
- // Server or Client
- case 'S': {
- role -= 1;
- break;
- }
- case 'C': {
- role += 1;
- break;
- }
- case 'k': {
- server_configuration.passphrase = std::string(optarg);
- client_configuration.passphrase = std::string(optarg);
- server_configuration.sign = true;
- break;
- }
-
- // Client specifc
- case 'b': {
- client_configuration.beta = std::stod(optarg);
- options = 1;
- break;
- }
- case 'd': {
- client_configuration.drop_factor = std::stod(optarg);
- options = 1;
- break;
- }
- case 'W': {
- client_configuration.window = std::stod(optarg);
- options = 1;
- break;
- }
- case 'M': {
- client_configuration.receive_buffer_size_ = std::stoull(optarg);
- options = 1;
- break;
- }
- case 'P': {
- client_configuration.producer_prefix_ = Prefix(optarg);
- client_configuration.secure_ = true;
- break;
- }
- case 'c': {
- client_configuration.producer_certificate = std::string(optarg);
- options = 1;
- break;
- }
- case 'i': {
- client_configuration.report_interval_milliseconds_ = std::stoul(optarg);
- options = 1;
- break;
- }
- case 't': {
- client_configuration.test_mode_ = true;
- options = 1;
- break;
- }
- case 'L': {
- client_configuration.interest_lifetime_ = std::stoul(optarg);
- options = 1;
- break;
- }
- // Server specific
- case 'A': {
- server_configuration.download_size = std::stoul(optarg);
- options = -1;
- break;
- }
- case 's': {
- server_configuration.payload_size_ = std::stoul(optarg);
- options = -1;
- break;
- }
- case 'r': {
- server_configuration.virtual_producer = false;
- options = -1;
- break;
- }
- case 'm': {
- server_configuration.manifest = true;
- options = -1;
- break;
- }
- case 'l': {
- server_configuration.live_production = true;
- options = -1;
- break;
- }
- case 'K': {
- server_configuration.keystore_name = std::string(optarg);
- server_configuration.sign = true;
- options = -1;
- break;
- }
- case 'y': {
- if (strncasecmp(optarg, "sha256", 6) == 0) {
- server_configuration.hash_algorithm = auth::CryptoHashType::SHA_256;
- } else if (strncasecmp(optarg, "sha512", 6) == 0) {
- server_configuration.hash_algorithm = auth::CryptoHashType::SHA_512;
- } else if (strncasecmp(optarg, "crc32", 5) == 0) {
- server_configuration.hash_algorithm = auth::CryptoHashType::CRC32C;
- } else {
- std::cerr << "Ignored unknown hash algorithm. Using SHA 256."
- << std::endl;
- }
- options = -1;
- break;
- }
- case 'p': {
- server_configuration.keystore_password = std::string(optarg);
- options = -1;
- break;
- }
- case 'x': {
- server_configuration.multiphase_produce_ = true;
- options = -1;
- break;
- }
- case 'B': {
- auto str = std::string(optarg);
- std::transform(str.begin(), str.end(), str.begin(), ::tolower);
- server_configuration.production_rate_ = str;
- options = -1;
- break;
- }
- case 'E': {
- server_configuration.keystore_name = std::string(optarg);
- server_configuration.secure_ = true;
- break;
- }
- case 'h':
- default:
- usage();
- return EXIT_FAILURE;
- }
- }
-
- if (options > 0 && role < 0) {
- std::cerr << "Client options cannot be used when using the "
- "software in server mode"
- << std::endl;
- usage();
- return EXIT_FAILURE;
- } else if (options < 0 && role > 0) {
- std::cerr << "Server options cannot be used when using the "
- "software in client mode"
- << std::endl;
- usage();
- return EXIT_FAILURE;
- } else if (!role) {
- std::cerr << "Please specify if running hiperf as client "
- "or server."
- << std::endl;
- usage();
- return EXIT_FAILURE;
- }
-
- if (argv[optind] == 0) {
- std::cerr << "Please specify the name/prefix to use." << std::endl;
- usage();
- return EXIT_FAILURE;
- } else {
- if (role > 0) {
- client_configuration.name = Name(argv[optind]);
- } else {
- server_configuration.name = Prefix(argv[optind]);
- }
- }
-
- if (log_file) {
-#ifndef _WIN32
- int fd = open(log_file, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR);
- dup2(fd, STDOUT_FILENO);
- dup2(STDOUT_FILENO, STDERR_FILENO);
- close(fd);
-#else
- int fd =
- _open(log_file, _O_WRONLY | _O_APPEND | _O_CREAT, _S_IWRITE | _S_IREAD);
- _dup2(fd, _fileno(stdout));
- _dup2(_fileno(stdout), _fileno(stderr));
- _close(fd);
-#endif
- }
-
-#ifndef _WIN32
- if (daemon) {
- utils::Daemonizator::daemonize(false);
- }
-#endif
-
- /**
- * IO module configuration
- */
- config.set();
-
- // Parse config file
- transport::interface::global_config::parseConfigurationFile(conf_file);
-
- if (role > 0) {
- HIperfClient c(client_configuration);
- if (c.setup() != ERROR_SETUP) {
- c.run();
- }
- } else if (role < 0) {
- HIperfServer s(server_configuration);
- if (s.setup() != ERROR_SETUP) {
- s.run();
- }
- } else {
- usage();
- return EXIT_FAILURE;
- }
-
-#ifdef _WIN32
- WSACleanup();
-#endif
-
- return 0;
-}
-
-} // end namespace interface
-} // end namespace transport
-
-int main(int argc, char *argv[]) {
- return transport::interface::main(argc, argv);
-}